diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 3af5bd41267..175db5d4202 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -92a14213215fd93df7240fa9d376a1213b1d5a74 +7b25b4dff4778fc4d6b5d6e10594814146b3e5dd The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug273.go b/gcc/testsuite/go.test/test/fixedbugs/bug273.go index c04f2116c5f..7305c6063cc 100644 --- a/gcc/testsuite/go.test/test/fixedbugs/bug273.go +++ b/gcc/testsuite/go.test/test/fixedbugs/bug273.go @@ -8,13 +8,15 @@ package main +import "unsafe" + var bug = false var minus1 = -1 var five = 5 -var big int64 = 10 | 1<<32 +var big int64 = 10 | 1<<40 -type block [1<<19]byte +type block [1 << 19]byte var g1 []block @@ -48,9 +50,10 @@ func bigcap() { g1 = make([]block, 10, big) } -type cblock [1<<16-1]byte +type cblock [1<<16 - 1]byte var g4 chan cblock + func badchancap() { g4 = make(chan cblock, minus1) } @@ -60,7 +63,8 @@ func bigchancap() { } func overflowchan() { - g4 = make(chan cblock, 1<<30) + const ptrSize = unsafe.Sizeof(uintptr(0)) + g4 = make(chan cblock, 1<<(30*(ptrSize/4))) } func main() { diff --git a/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go b/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go index 63aca2378ee..6bf315fcc2f 100644 --- a/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go +++ b/gcc/testsuite/go.test/test/fixedbugs/issue4085b.go @@ -1,6 +1,6 @@ // run -// Copyright 2013 The Go Authors. All rights reserved. +// 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. @@ -15,22 +15,31 @@ type T []int func main() { n := -1 - shouldPanic("len out of range", func() {_ = make(T, n)}) - shouldPanic("cap out of range", func() {_ = make(T, 0, n)}) + shouldPanic("len out of range", func() { _ = make(T, n) }) + shouldPanic("cap out of range", func() { _ = make(T, 0, n) }) + shouldPanic("len out of range", func() { _ = make(T, int64(n)) }) + shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) }) var t *byte if unsafe.Sizeof(t) == 8 { - n = 1<<20 - n <<= 20 - shouldPanic("len out of range", func() {_ = make(T, n)}) - shouldPanic("cap out of range", func() {_ = make(T, 0, n)}) - n <<= 20 - shouldPanic("len out of range", func() {_ = make(T, n)}) - shouldPanic("cap out of range", func() {_ = make(T, 0, n)}) + var n2 int64 = 1 << 50 + shouldPanic("len out of range", func() { _ = make(T, int(n2)) }) + shouldPanic("cap out of range", func() { _ = make(T, 0, int(n2)) }) + n2 = 1<<63 - 1 + shouldPanic("len out of range", func() { _ = make(T, int(n2)) }) + shouldPanic("cap out of range", func() { _ = make(T, 0, int(n2)) }) } else { n = 1<<31 - 1 - shouldPanic("len out of range", func() {_ = make(T, n)}) - shouldPanic("cap out of range", func() {_ = make(T, 0, n)}) + shouldPanic("len out of range", func() { _ = make(T, n) }) + shouldPanic("cap out of range", func() { _ = make(T, 0, n) }) + shouldPanic("len out of range", func() { _ = make(T, int64(n)) }) + shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) }) } + + // Test make in append panics since the gc compiler optimizes makes in appends. + shouldPanic("len out of range", func() { _ = append(T{}, make(T, n)...) }) + shouldPanic("cap out of range", func() { _ = append(T{}, make(T, 0, n)...) }) + shouldPanic("len out of range", func() { _ = append(T{}, make(T, int64(n))...) }) + shouldPanic("cap out of range", func() { _ = append(T{}, make(T, 0, int64(n))...) }) } func shouldPanic(str string, f func()) { @@ -44,6 +53,6 @@ func shouldPanic(str string, f func()) { panic("got panic " + s + ", want " + str) } }() - + f() } diff --git a/gotools/ChangeLog b/gotools/ChangeLog index 0e671860435..afcd7a211c1 100644 --- a/gotools/ChangeLog +++ b/gotools/ChangeLog @@ -1,3 +1,11 @@ +2018-09-24 Ian Lance Taylor + + * Makefile.am (mostlyclean-local): Run chmod on check-go-dir to + make sure it is writable. + (check-go-tools): Likewise. + (check-vet): Copy internal/objabi to check-vet-dir. + * Makefile.in: Rebuild. + 2018-05-09 Ian Lance Taylor * Makefile.am (check-go-tool): Don't copy zstdpkglist.go. diff --git a/gotools/Makefile.am b/gotools/Makefile.am index 06be89d582a..cb4ffe7a66f 100644 --- a/gotools/Makefile.am +++ b/gotools/Makefile.am @@ -123,6 +123,7 @@ MOSTLYCLEANFILES = \ *.sent mostlyclean-local: + chmod -R u+w check-go-dir rm -rf check-go-dir check-runtime-dir cgo-test-dir carchive-test-dir if NATIVE @@ -228,6 +229,7 @@ ECHO_ENV = PATH=`echo $(abs_builddir):$${PATH} | sed 's,::*,:,g;s,^:*,,;s,:*$$,, # check-go-tool runs `go test cmd/go` in our environment. check-go-tool: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check-gcc + chmod -R u+w check-go-dir rm -rf check-go-dir cmd_go-testlog $(MKDIR_P) check-go-dir/src/cmd/go cp $(cmdsrcdir)/go/*.go check-go-dir/src/cmd/go/ @@ -297,8 +299,10 @@ check-carchive-test: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check # check-vet runs `go test cmd/vet` in our environment. check-vet: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check-gcc rm -rf check-vet-dir cmd_vet-testlog - $(MKDIR_P) check-vet-dir/src/cmd + $(MKDIR_P) check-vet-dir/src/cmd/internal cp -r $(cmdsrcdir)/vet check-vet-dir/src/cmd/ + cp -r $(cmdsrcdir)/internal/objabi check-vet-dir/src/cmd/internal + cp $(libgodir)/objabi.go check-vet-dir/src/cmd/internal/objabi/ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \ abs_checkdir=`cd check-vet-dir && $(PWD_COMMAND)`; \ echo "cd check-vet-dir/src/cmd/vet && $(ECHO_ENV) GOPATH=$${abs_checkdir} $(abs_builddir)/go$(EXEEXT) test -test.short -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v" > cmd_vet-testlog diff --git a/gotools/Makefile.in b/gotools/Makefile.in index 503ec4eb446..acadfc64016 100644 --- a/gotools/Makefile.in +++ b/gotools/Makefile.in @@ -637,8 +637,8 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -@NATIVE_FALSE@uninstall-local: @NATIVE_FALSE@install-exec-local: +@NATIVE_FALSE@uninstall-local: clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-noinstPROGRAMS \ @@ -744,6 +744,7 @@ s-zdefaultcc: Makefile $(STAMP) $@ mostlyclean-local: + chmod -R u+w check-go-dir rm -rf check-go-dir check-runtime-dir cgo-test-dir carchive-test-dir @NATIVE_TRUE@go$(EXEEXT): $(go_cmd_go_files) $(LIBGOTOOL) $(LIBGODEP) @@ -807,6 +808,7 @@ mostlyclean-local: # check-go-tool runs `go test cmd/go` in our environment. @NATIVE_TRUE@check-go-tool: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check-gcc +@NATIVE_TRUE@ chmod -R u+w check-go-dir @NATIVE_TRUE@ rm -rf check-go-dir cmd_go-testlog @NATIVE_TRUE@ $(MKDIR_P) check-go-dir/src/cmd/go @NATIVE_TRUE@ cp $(cmdsrcdir)/go/*.go check-go-dir/src/cmd/go/ @@ -876,8 +878,10 @@ mostlyclean-local: # check-vet runs `go test cmd/vet` in our environment. @NATIVE_TRUE@check-vet: go$(EXEEXT) $(noinst_PROGRAMS) check-head check-gccgo check-gcc @NATIVE_TRUE@ rm -rf check-vet-dir cmd_vet-testlog -@NATIVE_TRUE@ $(MKDIR_P) check-vet-dir/src/cmd +@NATIVE_TRUE@ $(MKDIR_P) check-vet-dir/src/cmd/internal @NATIVE_TRUE@ cp -r $(cmdsrcdir)/vet check-vet-dir/src/cmd/ +@NATIVE_TRUE@ cp -r $(cmdsrcdir)/internal/objabi check-vet-dir/src/cmd/internal +@NATIVE_TRUE@ cp $(libgodir)/objabi.go check-vet-dir/src/cmd/internal/objabi/ @NATIVE_TRUE@ @abs_libgodir=`cd $(libgodir) && $(PWD_COMMAND)`; \ @NATIVE_TRUE@ abs_checkdir=`cd check-vet-dir && $(PWD_COMMAND)`; \ @NATIVE_TRUE@ echo "cd check-vet-dir/src/cmd/vet && $(ECHO_ENV) GOPATH=$${abs_checkdir} $(abs_builddir)/go$(EXEEXT) test -test.short -test.timeout=$(GOTOOLS_TEST_TIMEOUT)s -test.v" > cmd_vet-testlog diff --git a/libgo/MERGE b/libgo/MERGE index c54da0dcac1..9b907987def 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -1,4 +1,4 @@ -fe8a0d12b14108cbe2408b417afcaab722b0727c +41e62b8c49d21659b48a95216e3062032285250f The first line of this file holds the git revision number of the last merge done from the master library sources. diff --git a/libgo/Makefile.am b/libgo/Makefile.am index d847413d94c..373dd0cf73c 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -541,6 +541,7 @@ s-objabi: Makefile echo 'const defaultGO386 = `sse2`' >> objabi.go.tmp echo 'const defaultGOARM = `5`' >> objabi.go.tmp echo 'const defaultGOMIPS = `hardfloat`' >> objabi.go.tmp + echo 'const defaultGOMIPS64 = `hardfloat`' >> objabi.go.tmp echo 'const defaultGOOS = runtime.GOOS' >> objabi.go.tmp echo 'const defaultGOARCH = runtime.GOARCH' >> objabi.go.tmp echo 'const defaultGO_EXTLINK_ENABLED = ``' >> objabi.go.tmp @@ -608,7 +609,7 @@ noinst_DATA += zdefaultcc.go zstdpkglist.go: s-zstdpkglist; @true s-zstdpkglist: Makefile rm -f zstdpkglist.go.tmp - echo 'package build' > zstdpkglist.go.tmp + echo 'package goroot' > zstdpkglist.go.tmp echo "" >> zstdpkglist.go.tmp echo 'var stdpkg = map[string]bool{' >> zstdpkglist.go.tmp echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_/]*_c\.lo||g' | sed 's|\([a-z0-9_/]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp @@ -707,6 +708,7 @@ PACKAGES = $(shell cat $(srcdir)/libgo-packages.txt) libgo_go_objs = \ $(addsuffix .lo,$(PACKAGES)) \ bytes/index.lo \ + internal/bytealg/bytealg.lo \ reflect/makefunc_ffi_c.lo \ strings/index.lo \ $(syscall_lib_clone_lo) \ @@ -718,7 +720,8 @@ libgo_go_objs = \ log/syslog/syslog_c.lo \ $(os_lib_inotify_lo) \ runtime/internal/atomic_c.lo \ - sync/atomic_c.lo + sync/atomic_c.lo \ + internal/cpu/cpu_gccgo.lo libgo_ldflags = \ -version-info $(libtool_VERSION) $(PTHREAD_CFLAGS) $(AM_LDFLAGS) @@ -960,8 +963,8 @@ runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline extra_go_files_runtime_internal_sys = version.go runtime/internal/sys.lo.dep: $(extra_go_files_runtime_internal_sys) -extra_go_files_go_build = zstdpkglist.go -go/build.lo.dep: $(extra_go_files_go_build) +extra_go_files_internal_goroot = zstdpkglist.go +internal/goroot.lo.dep: $(extra_go_files_internal_goroot) extra_go_files_go_types = gccgosizes.go go/types.lo.dep: $(extra_go_files_go_types) @@ -976,6 +979,16 @@ extra_check_libs_cmd_go_internal_cache = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_generate = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_get = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_load = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_imports = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_modconv = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_modfetch = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_modfetch_codehost = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_modfile = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_modload = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_module = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_mvs = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_search = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_web2 = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_work = $(abs_builddir)/libgotool.a extra_check_libs_cmd_vet_internal_cfg = $(abs_builddir)/libgotool.a @@ -990,6 +1003,9 @@ bytes/index.lo: go/bytes/indexbyte.c runtime.inc strings/index.lo: go/strings/indexbyte.c runtime.inc @$(MKDIR_P) strings $(LTCOMPILE) -c -o $@ $(srcdir)/go/strings/indexbyte.c +internal/bytealg/bytealg.lo: go/internal/bytealg/bytealg.c runtime.inc + @$(MKDIR_P) internal/bytealg + $(LTCOMPILE) -c -o $@ $(srcdir)/go/internal/bytealg/bytealg.c # Use a C function with a fixed number of arguments to call a C # varargs function. @@ -1024,6 +1040,11 @@ syscall/wait.lo: go/syscall/wait.c runtime.inc @$(MKDIR_P) syscall $(LTCOMPILE) -c -o $@ $(srcdir)/go/syscall/wait.c +# internal/cpu needs some C code. +internal/cpu/cpu_gccgo.lo: go/internal/cpu/cpu_gccgo.c runtime.inc + @$(MKDIR_P) internal/cpu + $(LTCOMPILE) -c -o $@ $(srcdir)/go/internal/cpu/cpu_gccgo.c + # Solaris 11.4 changed the type of fields in struct stat. # Use a build tag, based on a configure check, to cope. if LIBGO_IS_SOLARIS diff --git a/libgo/Makefile.in b/libgo/Makefile.in index 6b3c5978701..dfc2c66199b 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -174,11 +174,12 @@ libgotool_a_OBJECTS = $(am_libgotool_a_OBJECTS) LTLIBRARIES = $(toolexeclib_LTLIBRARIES) @LIBGO_IS_LINUX_TRUE@am__DEPENDENCIES_1 = syscall/clone_linux.lo am__DEPENDENCIES_2 = $(addsuffix .lo,$(PACKAGES)) bytes/index.lo \ - reflect/makefunc_ffi_c.lo strings/index.lo \ - $(am__DEPENDENCIES_1) syscall/errno.lo syscall/signame.lo \ - syscall/wait.lo $(golang_org_x_net_lif_lo) \ + internal/bytealg/bytealg.lo reflect/makefunc_ffi_c.lo \ + strings/index.lo $(am__DEPENDENCIES_1) syscall/errno.lo \ + syscall/signame.lo syscall/wait.lo $(golang_org_x_net_lif_lo) \ $(golang_org_x_net_route_lo) log/syslog/syslog_c.lo \ - runtime/internal/atomic_c.lo sync/atomic_c.lo + runtime/internal/atomic_c.lo sync/atomic_c.lo \ + internal/cpu/cpu_gccgo.lo am__DEPENDENCIES_3 = am__DEPENDENCIES_4 = $(am__DEPENDENCIES_2) \ ../libbacktrace/libbacktrace.la $(am__DEPENDENCIES_3) \ @@ -824,6 +825,7 @@ PACKAGES = $(shell cat $(srcdir)/libgo-packages.txt) libgo_go_objs = \ $(addsuffix .lo,$(PACKAGES)) \ bytes/index.lo \ + internal/bytealg/bytealg.lo \ reflect/makefunc_ffi_c.lo \ strings/index.lo \ $(syscall_lib_clone_lo) \ @@ -835,7 +837,8 @@ libgo_go_objs = \ log/syslog/syslog_c.lo \ $(os_lib_inotify_lo) \ runtime/internal/atomic_c.lo \ - sync/atomic_c.lo + sync/atomic_c.lo \ + internal/cpu/cpu_gccgo.lo libgo_ldflags = \ -version-info $(libtool_VERSION) $(PTHREAD_CFLAGS) $(AM_LDFLAGS) @@ -999,7 +1002,7 @@ runtime_internal_sys_lo_check_GOCFLAGS = -fgo-compiling-runtime # Also use -fno-inline to get better results from the memory profiler. runtime_pprof_check_GOCFLAGS = -static-libgo -fno-inline extra_go_files_runtime_internal_sys = version.go -extra_go_files_go_build = zstdpkglist.go +extra_go_files_internal_goroot = zstdpkglist.go extra_go_files_go_types = gccgosizes.go extra_go_files_cmd_internal_objabi = objabi.go extra_go_files_cmd_go_internal_cfg = zdefaultcc.go @@ -1007,6 +1010,16 @@ extra_check_libs_cmd_go_internal_cache = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_generate = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_get = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_load = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_imports = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_modconv = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_modfetch = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_modfetch_codehost = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_modfile = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_modload = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_module = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_mvs = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_search = $(abs_builddir)/libgotool.a +extra_check_libs_cmd_go_internal_web2 = $(abs_builddir)/libgotool.a extra_check_libs_cmd_go_internal_work = $(abs_builddir)/libgotool.a extra_check_libs_cmd_vet_internal_cfg = $(abs_builddir)/libgotool.a @HAVE_STAT_TIMESPEC_FALSE@@LIBGO_IS_SOLARIS_TRUE@matchargs_os = @@ -2755,6 +2768,7 @@ s-objabi: Makefile echo 'const defaultGO386 = `sse2`' >> objabi.go.tmp echo 'const defaultGOARM = `5`' >> objabi.go.tmp echo 'const defaultGOMIPS = `hardfloat`' >> objabi.go.tmp + echo 'const defaultGOMIPS64 = `hardfloat`' >> objabi.go.tmp echo 'const defaultGOOS = runtime.GOOS' >> objabi.go.tmp echo 'const defaultGOARCH = runtime.GOARCH' >> objabi.go.tmp echo 'const defaultGO_EXTLINK_ENABLED = ``' >> objabi.go.tmp @@ -2816,7 +2830,7 @@ s-runtime-inc: runtime.lo Makefile zstdpkglist.go: s-zstdpkglist; @true s-zstdpkglist: Makefile rm -f zstdpkglist.go.tmp - echo 'package build' > zstdpkglist.go.tmp + echo 'package goroot' > zstdpkglist.go.tmp echo "" >> zstdpkglist.go.tmp echo 'var stdpkg = map[string]bool{' >> zstdpkglist.go.tmp echo $(libgo_go_objs) 'unsafe.lo' 'runtime/cgo.lo' | sed 's|[a-z0-9_/]*_c\.lo||g' | sed 's|\([a-z0-9_/]*\)\.lo|"\1": true,|g' >> zstdpkglist.go.tmp @@ -2943,7 +2957,7 @@ $(foreach package,$(GOTOOL_PACKAGES),$(eval $(call PACKAGE_template,$(package))) runtime.lo.dep: $(extra_go_files_runtime) syscall.lo.dep: $(extra_go_files_syscall) runtime/internal/sys.lo.dep: $(extra_go_files_runtime_internal_sys) -go/build.lo.dep: $(extra_go_files_go_build) +internal/goroot.lo.dep: $(extra_go_files_internal_goroot) go/types.lo.dep: $(extra_go_files_go_types) cmd/internal/objabi.lo.dep: $(extra_go_files_cmd_internal_objabi) cmd/go/internal/cfg.lo.dep: $(extra_go_files_cmd_go_internal_cfg) @@ -2958,6 +2972,9 @@ bytes/index.lo: go/bytes/indexbyte.c runtime.inc strings/index.lo: go/strings/indexbyte.c runtime.inc @$(MKDIR_P) strings $(LTCOMPILE) -c -o $@ $(srcdir)/go/strings/indexbyte.c +internal/bytealg/bytealg.lo: go/internal/bytealg/bytealg.c runtime.inc + @$(MKDIR_P) internal/bytealg + $(LTCOMPILE) -c -o $@ $(srcdir)/go/internal/bytealg/bytealg.c # Use a C function with a fixed number of arguments to call a C # varargs function. @@ -2992,6 +3009,11 @@ syscall/wait.lo: go/syscall/wait.c runtime.inc @$(MKDIR_P) syscall $(LTCOMPILE) -c -o $@ $(srcdir)/go/syscall/wait.c +# internal/cpu needs some C code. +internal/cpu/cpu_gccgo.lo: go/internal/cpu/cpu_gccgo.c runtime.inc + @$(MKDIR_P) internal/cpu + $(LTCOMPILE) -c -o $@ $(srcdir)/go/internal/cpu/cpu_gccgo.c + # Build golang_org/x/net/route only on BSD systems. @LIBGO_IS_BSD_TRUE@$(eval $(call PACKAGE_template,golang_org/x/net/route)) diff --git a/libgo/VERSION b/libgo/VERSION index 038f0b9313a..f3220fb7592 100644 --- a/libgo/VERSION +++ b/libgo/VERSION @@ -1 +1 @@ -go1.10.3 +go1.11 diff --git a/libgo/check-packages.txt b/libgo/check-packages.txt index 82a08c6554d..6c307d30085 100644 --- a/libgo/check-packages.txt +++ b/libgo/check-packages.txt @@ -3,9 +3,23 @@ archive/zip bufio bytes cmd/go/internal/cache +cmd/go/internal/dirhash cmd/go/internal/generate cmd/go/internal/get +cmd/go/internal/imports cmd/go/internal/load +cmd/go/internal/modconv +cmd/go/internal/modfetch +cmd/go/internal/modfetch/codehost +cmd/go/internal/modfile +cmd/go/internal/modload +cmd/go/internal/module +cmd/go/internal/mvs +cmd/go/internal/par +cmd/go/internal/search +cmd/go/internal/semver +cmd/go/internal/txtar +cmd/go/internal/web2 cmd/go/internal/work cmd/internal/buildid cmd/internal/edit @@ -29,6 +43,7 @@ crypto/dsa crypto/ecdsa crypto/elliptic crypto/hmac +crypto/internal/subtle crypto/md5 crypto/rand crypto/rc4 @@ -76,11 +91,15 @@ go/printer go/scanner go/token go/types +golang_org/x/crypto/internal/chacha20 golang_org/x/crypto/chacha20poly1305 golang_org/x/crypto/chacha20poly1305/internal/chacha20 golang_org/x/crypto/cryptobyte golang_org/x/crypto/curve25519 golang_org/x/crypto/poly1305 +golang_org/x/net/dns/dnsmessage +golang_org/x/net/http/httpguts +golang_org/x/net/http/httpproxy golang_org/x/net/http2/hpack golang_org/x/net/idna golang_org/x/net/lex/httplex @@ -98,6 +117,7 @@ image/draw image/jpeg image/png index/suffixarray +internal/cpu internal/poll internal/singleflight internal/trace diff --git a/libgo/go/archive/tar/common.go b/libgo/go/archive/tar/common.go index 4a2c173bf3a..dee9e47e4ae 100644 --- a/libgo/go/archive/tar/common.go +++ b/libgo/go/archive/tar/common.go @@ -56,7 +56,7 @@ func (he headerError) Error() string { const ( // Type '0' indicates a regular file. TypeReg = '0' - TypeRegA = '\x00' // For legacy support; use TypeReg instead + TypeRegA = '\x00' // Deprecated: Use TypeReg instead. // Type '1' to '6' are header-only flags and may not have a data body. TypeLink = '1' // Hard link @@ -138,7 +138,10 @@ var basicKeys = map[string]bool{ // should do so by creating a new Header and copying the fields // that they are interested in preserving. type Header struct { - Typeflag byte // Type of header entry (should be TypeReg for most files) + // Typeflag is the type of header entry. + // The zero value is automatically promoted to either TypeReg or TypeDir + // depending on the presence of a trailing slash in Name. + Typeflag byte Name string // Name of file entry Linkname string // Target name of link (valid for TypeLink or TypeSymlink) @@ -184,7 +187,7 @@ type Header struct { // The key and value should be non-empty UTF-8 strings. // // When Writer.WriteHeader is called, PAX records derived from the - // the other fields in Header take precedence over PAXRecords. + // other fields in Header take precedence over PAXRecords. PAXRecords map[string]string // Format specifies the format of the tar header. diff --git a/libgo/go/archive/tar/format.go b/libgo/go/archive/tar/format.go index 6e29698a14a..1f89d0c59a1 100644 --- a/libgo/go/archive/tar/format.go +++ b/libgo/go/archive/tar/format.go @@ -94,7 +94,7 @@ const ( // application can only parse GNU formatted archives. // // Reference: - // http://www.gnu.org/software/tar/manual/html_node/Standard.html + // https://www.gnu.org/software/tar/manual/html_node/Standard.html FormatGNU // Schily's tar format, which is incompatible with USTAR. diff --git a/libgo/go/archive/tar/reader.go b/libgo/go/archive/tar/reader.go index f4eeb557be9..39437185179 100644 --- a/libgo/go/archive/tar/reader.go +++ b/libgo/go/archive/tar/reader.go @@ -64,7 +64,6 @@ func (tr *Reader) next() (*Header, error) { // normally be visible to the outside. As such, this loop iterates through // one or more "header files" until it finds a "normal file". format := FormatUSTAR | FormatPAX | FormatGNU -loop: for { // Discard the remainder of the file and any padding. if err := discard(tr.r, tr.curr.PhysicalRemaining()); err != nil { @@ -102,7 +101,7 @@ loop: Format: format, }, nil } - continue loop // This is a meta header affecting the next header + continue // This is a meta header affecting the next header case TypeGNULongName, TypeGNULongLink: format.mayOnlyBe(FormatGNU) realname, err := ioutil.ReadAll(tr) @@ -117,7 +116,7 @@ loop: case TypeGNULongLink: gnuLongLink = p.parseString(realname) } - continue loop // This is a meta header affecting the next header + continue // This is a meta header affecting the next header default: // The old GNU sparse format is handled here since it is technically // just a regular file with additional attributes. @@ -131,8 +130,12 @@ loop: if gnuLongLink != "" { hdr.Linkname = gnuLongLink } - if hdr.Typeflag == TypeRegA && strings.HasSuffix(hdr.Name, "/") { - hdr.Typeflag = TypeDir // Legacy archives use trailing slash for directories + if hdr.Typeflag == TypeRegA { + if strings.HasSuffix(hdr.Name, "/") { + hdr.Typeflag = TypeDir // Legacy archives use trailing slash for directories + } else { + hdr.Typeflag = TypeReg + } } // The extended headers may have updated the size. @@ -200,7 +203,7 @@ func (tr *Reader) handleSparseFile(hdr *Header, rawHdr *block) error { // readGNUSparsePAXHeaders checks the PAX headers for GNU sparse headers. // If they are found, then this function reads the sparse map and returns it. // This assumes that 0.0 headers have already been converted to 0.1 headers -// by the the PAX header parsing logic. +// by the PAX header parsing logic. func (tr *Reader) readGNUSparsePAXHeaders(hdr *Header) (sparseDatas, error) { // Identify the version of GNU headers. var is1x0 bool diff --git a/libgo/go/archive/tar/reader_test.go b/libgo/go/archive/tar/reader_test.go index a6832d33b1b..f153b668def 100644 --- a/libgo/go/archive/tar/reader_test.go +++ b/libgo/go/archive/tar/reader_test.go @@ -189,7 +189,7 @@ func TestReader(t *testing.T) { Gid: 5000, Size: 5, ModTime: time.Unix(1244593104, 0), - Typeflag: '\x00', + Typeflag: '0', }, { Name: "small2.txt", Mode: 0444, @@ -197,7 +197,7 @@ func TestReader(t *testing.T) { Gid: 5000, Size: 11, ModTime: time.Unix(1244593104, 0), - Typeflag: '\x00', + Typeflag: '0', }}, }, { file: "testdata/pax.tar", @@ -378,9 +378,9 @@ func TestReader(t *testing.T) { "security.selinux": "unconfined_u:object_r:default_t:s0\x00", }, PAXRecords: map[string]string{ - "mtime": "1386065770.449252304", - "atime": "1389782991.41987522", - "ctime": "1386065770.449252304", + "mtime": "1386065770.449252304", + "atime": "1389782991.41987522", + "ctime": "1386065770.449252304", "SCHILY.xattr.security.selinux": "unconfined_u:object_r:default_t:s0\x00", }, Format: FormatPAX, @@ -534,9 +534,10 @@ func TestReader(t *testing.T) { // a buggy pre-Go1.8 tar.Writer. file: "testdata/invalid-go17.tar", headers: []*Header{{ - Name: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/foo", - Uid: 010000000, - ModTime: time.Unix(0, 0), + Name: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/foo", + Uid: 010000000, + ModTime: time.Unix(0, 0), + Typeflag: '0', }}, }, { // USTAR archive with a regular entry with non-zero device numbers. diff --git a/libgo/go/archive/tar/tar_test.go b/libgo/go/archive/tar/tar_test.go index af80d6e0c15..2676853122a 100644 --- a/libgo/go/archive/tar/tar_test.go +++ b/libgo/go/archive/tar/tar_test.go @@ -306,6 +306,7 @@ func TestRoundTrip(t *testing.T) { ModTime: time.Now().Round(time.Second), PAXRecords: map[string]string{"uid": "2097152"}, Format: FormatPAX, + Typeflag: TypeReg, } if err := tw.WriteHeader(hdr); err != nil { t.Fatalf("tw.WriteHeader: %v", err) diff --git a/libgo/go/archive/tar/testdata/file-and-dir.tar b/libgo/go/archive/tar/testdata/file-and-dir.tar new file mode 100644 index 00000000000..c18d4283e38 Binary files /dev/null and b/libgo/go/archive/tar/testdata/file-and-dir.tar differ diff --git a/libgo/go/archive/tar/testdata/trailing-slash.tar b/libgo/go/archive/tar/testdata/trailing-slash.tar index bf1b2ec426b..93718b30348 100644 Binary files a/libgo/go/archive/tar/testdata/trailing-slash.tar and b/libgo/go/archive/tar/testdata/trailing-slash.tar differ diff --git a/libgo/go/archive/tar/writer.go b/libgo/go/archive/tar/writer.go index 97d23f80388..e80498d03e3 100644 --- a/libgo/go/archive/tar/writer.go +++ b/libgo/go/archive/tar/writer.go @@ -5,7 +5,6 @@ package tar import ( - "bytes" "fmt" "io" "path" @@ -71,6 +70,16 @@ func (tw *Writer) WriteHeader(hdr *Header) error { } tw.hdr = *hdr // Shallow copy of Header + // Avoid usage of the legacy TypeRegA flag, and automatically promote + // it to use TypeReg or TypeDir. + if tw.hdr.Typeflag == TypeRegA { + if strings.HasSuffix(tw.hdr.Name, "/") { + tw.hdr.Typeflag = TypeDir + } else { + tw.hdr.Typeflag = TypeReg + } + } + // Round ModTime and ignore AccessTime and ChangeTime unless // the format is explicitly chosen. // This ensures nominal usage of WriteHeader (without specifying the format) @@ -166,7 +175,7 @@ func (tw *Writer) writePAXHeader(hdr *Header, paxHdrs map[string]string) error { sort.Strings(keys) // Write each record to a buffer. - var buf bytes.Buffer + var buf strings.Builder for _, k := range keys { rec, err := formatPAXRecord(k, paxHdrs[k]) if err != nil { diff --git a/libgo/go/archive/tar/writer_test.go b/libgo/go/archive/tar/writer_test.go index 24e8da271c2..30556d27d02 100644 --- a/libgo/go/archive/tar/writer_test.go +++ b/libgo/go/archive/tar/writer_test.go @@ -461,6 +461,15 @@ func TestWriter(t *testing.T) { testHeader{Header{Name: strings.Repeat("123456789/", 30)}, nil}, testClose{nil}, }, + }, { + // Automatically promote zero value of Typeflag depending on the name. + file: "testdata/file-and-dir.tar", + tests: []testFnc{ + testHeader{Header{Name: "small.txt", Size: 5}, nil}, + testWrite{"Kilts", 5, nil}, + testHeader{Header{Name: "dir/"}, nil}, + testClose{nil}, + }, }} equalError := func(x, y error) bool { @@ -809,8 +818,8 @@ func TestValidTypeflagWithPAXHeader(t *testing.T) { if err != nil { t.Fatalf("Failed to read header: %s", err) } - if header.Typeflag != 0 { - t.Fatalf("Typeflag should've been 0, found %d", header.Typeflag) + if header.Typeflag != TypeReg { + t.Fatalf("Typeflag should've been %d, found %d", TypeReg, header.Typeflag) } } } diff --git a/libgo/go/archive/zip/struct.go b/libgo/go/archive/zip/struct.go index f613ebdc344..c90151d9d44 100644 --- a/libgo/go/archive/zip/struct.go +++ b/libgo/go/archive/zip/struct.go @@ -81,8 +81,17 @@ const ( // See the zip spec for details. type FileHeader struct { // Name is the name of the file. - // It must be a relative path, not start with a drive letter (e.g. C:), - // and must use forward slashes instead of back slashes. + // + // It must be a relative path, not start with a drive letter (such as "C:"), + // and must use forward slashes instead of back slashes. A trailing slash + // indicates that this file is a directory and should have no data. + // + // When reading zip files, the Name field is populated from + // the zip file directly and is not validated for correctness. + // It is the caller's responsibility to sanitize it as + // appropriate, including canonicalizing slash directions, + // validating that paths are relative, and preventing path + // traversal through filenames ("../../../"). Name string // Comment is any arbitrary user-defined string shorter than 64KiB. @@ -201,7 +210,7 @@ func timeZone(offset time.Duration) *time.Location { // msDosTimeToTime converts an MS-DOS date and time into a time.Time. // The resolution is 2s. -// See: http://msdn.microsoft.com/en-us/library/ms724247(v=VS.85).aspx +// See: https://msdn.microsoft.com/en-us/library/ms724247(v=VS.85).aspx func msDosTimeToTime(dosDate, dosTime uint16) time.Time { return time.Date( // date bits 0-4: day of month; 5-8: month; 9-15: years since 1980 @@ -221,7 +230,7 @@ func msDosTimeToTime(dosDate, dosTime uint16) time.Time { // timeToMsDosTime converts a time.Time to an MS-DOS date and time. // The resolution is 2s. -// See: http://msdn.microsoft.com/en-us/library/ms724274(v=VS.85).aspx +// See: https://msdn.microsoft.com/en-us/library/ms724274(v=VS.85).aspx func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16) { fDate = uint16(t.Day() + int(t.Month())<<5 + (t.Year()-1980)<<9) fTime = uint16(t.Second()/2 + t.Minute()<<5 + t.Hour()<<11) diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go index 14a5ee48c11..5f0c0a1a555 100644 --- a/libgo/go/archive/zip/writer.go +++ b/libgo/go/archive/zip/writer.go @@ -11,6 +11,7 @@ import ( "hash" "hash/crc32" "io" + "strings" "unicode/utf8" ) @@ -71,7 +72,7 @@ func (w *Writer) SetComment(comment string) error { } // Close finishes writing the zip file by writing the central directory. -// It does not (and cannot) close the underlying writer. +// It does not close the underlying writer. func (w *Writer) Close() error { if w.last != nil && !w.last.closed { if err := w.last.close(); err != nil { @@ -209,7 +210,8 @@ func (w *Writer) Close() error { // The file contents will be compressed using the Deflate method. // The name must be a relative path: it must not start with a drive // letter (e.g. C:) or leading slash, and only forward slashes are -// allowed. +// allowed. To create a directory instead of a file, add a trailing +// slash to the name. // The file's contents must be written to the io.Writer before the next // call to Create, CreateHeader, or Close. func (w *Writer) Create(name string) (io.Writer, error) { @@ -261,8 +263,6 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) { return nil, errors.New("archive/zip: invalid duplicate FileHeader") } - fh.Flags |= 0x8 // we will write a data descriptor - // The ZIP format has a sad state of affairs regarding character encoding. // Officially, the name and comment fields are supposed to be encoded // in CP-437 (which is mostly compatible with ASCII), unless the UTF-8 @@ -319,35 +319,58 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) { fh.Extra = append(fh.Extra, mbuf[:]...) } - fw := &fileWriter{ - zipw: w.cw, - compCount: &countWriter{w: w.cw}, - crc32: crc32.NewIEEE(), - } - comp := w.compressor(fh.Method) - if comp == nil { - return nil, ErrAlgorithm - } - var err error - fw.comp, err = comp(fw.compCount) - if err != nil { - return nil, err - } - fw.rawCount = &countWriter{w: fw.comp} - + var ( + ow io.Writer + fw *fileWriter + ) h := &header{ FileHeader: fh, offset: uint64(w.cw.count), } - w.dir = append(w.dir, h) - fw.header = h + if strings.HasSuffix(fh.Name, "/") { + // Set the compression method to Store to ensure data length is truly zero, + // which the writeHeader method always encodes for the size fields. + // This is necessary as most compression formats have non-zero lengths + // even when compressing an empty string. + fh.Method = Store + fh.Flags &^= 0x8 // we will not write a data descriptor + + // Explicitly clear sizes as they have no meaning for directories. + fh.CompressedSize = 0 + fh.CompressedSize64 = 0 + fh.UncompressedSize = 0 + fh.UncompressedSize64 = 0 + + ow = dirWriter{} + } else { + fh.Flags |= 0x8 // we will write a data descriptor + + fw = &fileWriter{ + zipw: w.cw, + compCount: &countWriter{w: w.cw}, + crc32: crc32.NewIEEE(), + } + comp := w.compressor(fh.Method) + if comp == nil { + return nil, ErrAlgorithm + } + var err error + fw.comp, err = comp(fw.compCount) + if err != nil { + return nil, err + } + fw.rawCount = &countWriter{w: fw.comp} + fw.header = h + ow = fw + } + w.dir = append(w.dir, h) if err := writeHeader(w.cw, fh); err != nil { return nil, err } - + // If we're creating a directory, fw is nil. w.last = fw - return fw, nil + return ow, nil } func writeHeader(w io.Writer, h *FileHeader) error { @@ -400,6 +423,15 @@ func (w *Writer) compressor(method uint16) Compressor { return comp } +type dirWriter struct{} + +func (dirWriter) Write(b []byte) (int, error) { + if len(b) == 0 { + return 0, nil + } + return 0, errors.New("zip: write to directory") +} + type fileWriter struct { *header zipw io.Writer diff --git a/libgo/go/archive/zip/writer_test.go b/libgo/go/archive/zip/writer_test.go index 38f32296fa8..1fedfd85e82 100644 --- a/libgo/go/archive/zip/writer_test.go +++ b/libgo/go/archive/zip/writer_test.go @@ -6,6 +6,7 @@ package zip import ( "bytes" + "encoding/binary" "fmt" "io" "io/ioutil" @@ -299,6 +300,59 @@ func TestWriterFlush(t *testing.T) { } } +func TestWriterDir(t *testing.T) { + w := NewWriter(ioutil.Discard) + dw, err := w.Create("dir/") + if err != nil { + t.Fatal(err) + } + if _, err := dw.Write(nil); err != nil { + t.Errorf("Write(nil) to directory: got %v, want nil", err) + } + if _, err := dw.Write([]byte("hello")); err == nil { + t.Error(`Write("hello") to directory: got nil error, want non-nil`) + } +} + +func TestWriterDirAttributes(t *testing.T) { + var buf bytes.Buffer + w := NewWriter(&buf) + if _, err := w.CreateHeader(&FileHeader{ + Name: "dir/", + Method: Deflate, + CompressedSize64: 1234, + UncompressedSize64: 5678, + }); err != nil { + t.Fatal(err) + } + if err := w.Close(); err != nil { + t.Fatal(err) + } + b := buf.Bytes() + + var sig [4]byte + binary.LittleEndian.PutUint32(sig[:], uint32(fileHeaderSignature)) + + idx := bytes.Index(b, sig[:]) + if idx == -1 { + t.Fatal("file header not found") + } + b = b[idx:] + + if !bytes.Equal(b[6:10], []byte{0, 0, 0, 0}) { // FileHeader.Flags: 0, FileHeader.Method: 0 + t.Errorf("unexpected method and flags: %v", b[6:10]) + } + + if !bytes.Equal(b[14:26], make([]byte, 12)) { // FileHeader.{CRC32,CompressSize,UncompressedSize} all zero. + t.Errorf("unexpected crc, compress and uncompressed size to be 0 was: %v", b[14:26]) + } + + binary.LittleEndian.PutUint32(sig[:], uint32(dataDescriptorSignature)) + if bytes.Index(b, sig[:]) != -1 { + t.Error("there should be no data descriptor") + } +} + func testCreate(t *testing.T, w *Writer, wt *WriteTest) { header := &FileHeader{ Name: wt.Name, diff --git a/libgo/go/archive/zip/zip_test.go b/libgo/go/archive/zip/zip_test.go index 7e02cb0eeaa..50218a2bbd7 100644 --- a/libgo/go/archive/zip/zip_test.go +++ b/libgo/go/archive/zip/zip_test.go @@ -15,6 +15,7 @@ import ( "internal/testenv" "io" "io/ioutil" + "runtime" "sort" "strings" "testing" @@ -140,14 +141,7 @@ func (r *rleBuffer) Write(p []byte) (n int, err error) { rp = &r.buf[len(r.buf)-1] // Fast path, if p is entirely the same byte repeated. if lastByte := rp.b; len(p) > 0 && p[0] == lastByte { - all := true - for _, b := range p { - if b != lastByte { - all = false - break - } - } - if all { + if bytes.Count(p, []byte{lastByte}) == len(p) { rp.n += int64(len(p)) return len(p), nil } @@ -165,6 +159,25 @@ func (r *rleBuffer) Write(p []byte) (n int, err error) { return len(p), nil } +func min(x, y int) int { + if x < y { + return x + } + return y +} + +func memset(a []byte, b byte) { + if len(a) == 0 { + return + } + // Double, until we reach power of 2 >= len(a), same as bytes.Repeat, + // but without allocation. + a[0] = b + for i, l := 1, len(a); i < l; i *= 2 { + copy(a[i:], a[:i]) + } +} + func (r *rleBuffer) ReadAt(p []byte, off int64) (n int, err error) { if len(p) == 0 { return @@ -176,16 +189,13 @@ func (r *rleBuffer) ReadAt(p []byte, off int64) (n int, err error) { parts := r.buf[skipParts:] if len(parts) > 0 { skipBytes := off - parts[0].off - for len(parts) > 0 { - part := parts[0] - for i := skipBytes; i < part.n; i++ { - if n == len(p) { - return - } - p[n] = part.b - n++ + for _, part := range parts { + repeat := min(int(part.n-skipBytes), len(p)-n) + memset(p[n:n+repeat], part.b) + n += repeat + if n == len(p) { + return } - parts = parts[1:] skipBytes = 0 } } @@ -452,6 +462,9 @@ func suffixIsZip64(t *testing.T, zip sizedReaderAt) bool { // Zip64 is required if the total size of the records is uint32max. func TestZip64LargeDirectory(t *testing.T) { + if runtime.GOARCH == "wasm" { + t.Skip("too slow on wasm") + } if testing.Short() { t.Skip("skipping in short mode") } diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go index ad9c9f5ddf7..72545a75095 100644 --- a/libgo/go/bufio/bufio.go +++ b/libgo/go/bufio/bufio.go @@ -462,6 +462,8 @@ func (b *Reader) ReadString(delim byte) (string, error) { // WriteTo implements io.WriterTo. // This may make multiple calls to the Read method of the underlying Reader. +// If the underlying reader supports the WriteTo method, +// this calls the underlying WriteTo without buffering. func (b *Reader) WriteTo(w io.Writer) (n int64, err error) { n, err = b.writeBuf(w) if err != nil { @@ -684,7 +686,9 @@ func (b *Writer) WriteString(s string) (int, error) { return nn, nil } -// ReadFrom implements io.ReaderFrom. +// ReadFrom implements io.ReaderFrom. If the underlying writer +// supports the ReadFrom method, and b has no buffered data yet, +// this calls the underlying ReadFrom without buffering. func (b *Writer) ReadFrom(r io.Reader) (n int64, err error) { if b.Buffered() == 0 { if w, ok := b.wr.(io.ReaderFrom); ok { diff --git a/libgo/go/bufio/scan.go b/libgo/go/bufio/scan.go index 40aaa4ab817..cefd2614647 100644 --- a/libgo/go/bufio/scan.go +++ b/libgo/go/bufio/scan.go @@ -45,14 +45,19 @@ type Scanner struct { // input. The arguments are an initial substring of the remaining unprocessed // data and a flag, atEOF, that reports whether the Reader has no more data // to give. The return values are the number of bytes to advance the input -// and the next token to return to the user, plus an error, if any. If the -// data does not yet hold a complete token, for instance if it has no newline -// while scanning lines, SplitFunc can return (0, nil, nil) to signal the -// Scanner to read more data into the slice and try again with a longer slice -// starting at the same point in the input. +// and the next token to return to the user, if any, plus an error, if any. // -// If the returned error is non-nil, scanning stops and the error -// is returned to the client. +// Scanning stops if the function returns an error, in which case some of +// the input may be discarded. +// +// 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 +// Scanner reads more data and continues scanning; if there is no more +// data--if atEOF was true--the Scanner returns. If the data does not +// yet hold a complete token, for instance if it has no newline while +// scanning lines, a SplitFunc can return (0, nil, nil) to signal the +// Scanner to read more data into the slice and try again with a +// longer slice starting at the same point in the input. // // The function is never called with an empty data slice unless atEOF // is true. If atEOF is true, however, data may be non-empty and, diff --git a/libgo/go/bytes/buffer.go b/libgo/go/bytes/buffer.go index dc9d5e95d32..a2eca2ed129 100644 --- a/libgo/go/bytes/buffer.go +++ b/libgo/go/bytes/buffer.go @@ -202,6 +202,7 @@ func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) { b.lastRead = opInvalid for { i := b.grow(MinRead) + b.buf = b.buf[:i] m, e := r.Read(b.buf[i:cap(b.buf)]) if m < 0 { panic(errNegativeRead) diff --git a/libgo/go/bytes/buffer_test.go b/libgo/go/bytes/buffer_test.go index e4bbc12f6a1..acbe5ca0c49 100644 --- a/libgo/go/bytes/buffer_test.go +++ b/libgo/go/bytes/buffer_test.go @@ -269,6 +269,39 @@ func TestReadFrom(t *testing.T) { } } +type panicReader struct{ panic bool } + +func (r panicReader) Read(p []byte) (int, error) { + if r.panic { + panic(nil) + } + return 0, io.EOF +} + +// Make sure that an empty Buffer remains empty when +// it is "grown" before a Read that panics +func TestReadFromPanicReader(t *testing.T) { + + // First verify non-panic behaviour + var buf Buffer + i, err := buf.ReadFrom(panicReader{}) + if err != nil { + t.Fatal(err) + } + if i != 0 { + t.Fatalf("unexpected return from bytes.ReadFrom (1): got: %d, want %d", i, 0) + } + check(t, "TestReadFromPanicReader (1)", &buf, "") + + // Confirm that when Reader panics, the emtpy buffer remains empty + var buf2 Buffer + defer func() { + recover() + check(t, "TestReadFromPanicReader (2)", &buf2, "") + }() + buf2.ReadFrom(panicReader{panic: true}) +} + func TestReadFromNegativeReader(t *testing.T) { var b Buffer defer func() { diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go index 9af177fa882..437a6e12df8 100644 --- a/libgo/go/bytes/bytes.go +++ b/libgo/go/bytes/bytes.go @@ -7,6 +7,7 @@ package bytes import ( + "internal/bytealg" "unicode" "unicode/utf8" ) @@ -46,12 +47,16 @@ func explode(s []byte, n int) [][]byte { return a[0:na] } -// countGeneric actually implements Count -func countGeneric(s, sep []byte) int { +// Count counts the number of non-overlapping instances of sep in s. +// If sep is an empty slice, Count returns 1 + the number of UTF-8-encoded code points in s. +func Count(s, sep []byte) int { // special case if len(sep) == 0 { return utf8.RuneCount(s) + 1 } + if len(sep) == 1 { + return bytealg.Count(s, sep[0]) + } n := 0 for { i := Index(s, sep) @@ -800,9 +805,9 @@ func EqualFold(s, t []byte) bool { tr, sr = sr, tr } // Fast check for ASCII. - if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' { - // ASCII, and sr is upper case. tr must be lower case. - if tr == sr+'a'-'A' { + if tr < utf8.RuneSelf { + // ASCII only, sr/tr must be upper/lower case + if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' { continue } return false @@ -824,6 +829,92 @@ func EqualFold(s, t []byte) bool { return len(s) == len(t) } +// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. +func Index(s, sep []byte) int { + n := len(sep) + switch { + case n == 0: + return 0 + case n == 1: + return IndexByte(s, sep[0]) + case n == len(s): + if Equal(sep, s) { + return 0 + } + return -1 + case n > len(s): + return -1 + case n <= bytealg.MaxLen: + // Use brute force when s and sep both are small + if len(s) <= bytealg.MaxBruteForce { + return bytealg.Index(s, sep) + } + c := sep[0] + i := 0 + t := s[:len(s)-n+1] + fails := 0 + for i < len(t) { + if t[i] != c { + // IndexByte is faster than bytealg.Index, so use it as long as + // we're not getting lots of false positives. + o := IndexByte(t[i:], c) + if o < 0 { + return -1 + } + i += o + } + if Equal(s[i:i+n], sep) { + return i + } + fails++ + i++ + // Switch to bytealg.Index when IndexByte produces too many false positives. + if fails > bytealg.Cutover(i) { + r := bytealg.Index(s[i:], sep) + if r >= 0 { + return r + i + } + return -1 + } + } + return -1 + } + c := sep[0] + i := 0 + fails := 0 + t := s[:len(s)-n+1] + for i < len(t) { + if t[i] != c { + o := IndexByte(t[i:], c) + if o < 0 { + break + } + i += o + } + if Equal(s[i:i+n], sep) { + return i + } + i++ + fails++ + if fails >= 4+i>>4 && i < len(t) { + // Give up on IndexByte, it isn't skipping ahead + // far enough to be better than Rabin-Karp. + // Experiments (using IndexPeriodic) suggest + // the cutover is about 16 byte skips. + // TODO: if large prefixes of sep are matching + // we should cutover at even larger average skips, + // because Equal becomes that much more expensive. + // This code does not take that effect into account. + j := indexRabinKarp(s[i:], sep) + if j < 0 { + return -1 + } + return i + j + } + } + return -1 +} + func indexRabinKarp(s, sep []byte) int { // Rabin-Karp search hashsep, pow := hashStr(sep) diff --git a/libgo/go/bytes/bytes_amd64.go b/libgo/go/bytes/bytes_amd64.go deleted file mode 100644 index 2fbbbb0d877..00000000000 --- a/libgo/go/bytes/bytes_amd64.go +++ /dev/null @@ -1,90 +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. - -// +build ignore - -package bytes - -import "internal/cpu" - -//go:noescape - -// indexShortStr returns the index of the first instance of c in s, or -1 if c is not present in s. -// indexShortStr requires 2 <= len(c) <= shortStringLen -func indexShortStr(s, c []byte) int // ../runtime/asm_amd64.s -func countByte(s []byte, c byte) int // ../runtime/asm_amd64.s - -var shortStringLen int - -func init() { - if cpu.X86.HasAVX2 { - shortStringLen = 63 - } else { - shortStringLen = 31 - } -} - -// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. -func Index(s, sep []byte) int { - n := len(sep) - switch { - case n == 0: - return 0 - case n == 1: - return IndexByte(s, sep[0]) - case n == len(s): - if Equal(sep, s) { - return 0 - } - return -1 - case n > len(s): - return -1 - case n <= shortStringLen: - // Use brute force when s and sep both are small - if len(s) <= 64 { - return indexShortStr(s, sep) - } - c := sep[0] - i := 0 - t := s[:len(s)-n+1] - fails := 0 - for i < len(t) { - if t[i] != c { - // IndexByte skips 16/32 bytes per iteration, - // so it's faster than indexShortStr. - o := IndexByte(t[i:], c) - if o < 0 { - return -1 - } - i += o - } - if Equal(s[i:i+n], sep) { - return i - } - fails++ - i++ - // Switch to indexShortStr when IndexByte produces too many false positives. - // Too many means more that 1 error per 8 characters. - // Allow some errors in the beginning. - if fails > (i+16)/8 { - r := indexShortStr(s[i:], sep) - if r >= 0 { - return r + i - } - return -1 - } - } - return -1 - } - return indexRabinKarp(s, sep) -} - -// Count counts the number of non-overlapping instances of sep in s. -// If sep is an empty slice, Count returns 1 + the number of UTF-8-encoded code points in s. -func Count(s, sep []byte) int { - if len(sep) == 1 && cpu.X86.HasPOPCNT { - return countByte(s, sep[0]) - } - return countGeneric(s, sep) -} diff --git a/libgo/go/bytes/bytes_arm64.go b/libgo/go/bytes/bytes_arm64.go deleted file mode 100644 index 1213b067a9d..00000000000 --- a/libgo/go/bytes/bytes_arm64.go +++ /dev/null @@ -1,70 +0,0 @@ -// 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. - -// +build ignore - -package bytes - -func countByte(s []byte, c byte) int // bytes_arm64.s - -// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. -func Index(s, sep []byte) int { - n := len(sep) - switch { - case n == 0: - return 0 - case n == 1: - return IndexByte(s, sep[0]) - case n == len(s): - if Equal(sep, s) { - return 0 - } - return -1 - case n > len(s): - return -1 - } - c := sep[0] - i := 0 - fails := 0 - t := s[:len(s)-n+1] - for i < len(t) { - if t[i] != c { - o := IndexByte(t[i:], c) - if o < 0 { - break - } - i += o - } - if Equal(s[i:i+n], sep) { - return i - } - i++ - fails++ - if fails >= 4+i>>4 && i < len(t) { - // Give up on IndexByte, it isn't skipping ahead - // far enough to be better than Rabin-Karp. - // Experiments (using IndexPeriodic) suggest - // the cutover is about 16 byte skips. - // TODO: if large prefixes of sep are matching - // we should cutover at even larger average skips, - // because Equal becomes that much more expensive. - // This code does not take that effect into account. - j := indexRabinKarp(s[i:], sep) - if j < 0 { - return -1 - } - return i + j - } - } - return -1 -} - -// Count counts the number of non-overlapping instances of sep in s. -// If sep is an empty slice, Count returns 1 + the number of UTF-8-encoded code points in s. -func Count(s, sep []byte) int { - if len(sep) == 1 { - return countByte(s, sep[0]) - } - return countGeneric(s, sep) -} diff --git a/libgo/go/bytes/bytes_decl.go b/libgo/go/bytes/bytes_decl.go index df0614fed0d..af0f8b179fd 100644 --- a/libgo/go/bytes/bytes_decl.go +++ b/libgo/go/bytes/bytes_decl.go @@ -6,19 +6,19 @@ package bytes //go:noescape -// IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s. -func IndexByte(s []byte, c byte) int // ../runtime/asm_$GOARCH.s +// IndexByte returns the index of the first instance of c in b, or -1 if c is not present in b. +func IndexByte(b []byte, c byte) int // in internal/bytealg //go:noescape // Equal returns a boolean reporting whether a and b // are the same length and contain the same bytes. // A nil argument is equivalent to an empty slice. -func Equal(a, b []byte) bool // ../runtime/asm_$GOARCH.s +func Equal(a, b []byte) bool // in internal/bytealg //go:noescape // Compare returns an integer comparing two byte slices lexicographically. // The result will be 0 if a==b, -1 if a < b, and +1 if a > b. // A nil argument is equivalent to an empty slice. -func Compare(a, b []byte) int // ../runtime/noasm.go or ../runtime/asm_{386,amd64}.s +func Compare(a, b []byte) int // in internal/bytealg diff --git a/libgo/go/bytes/bytes_generic.go b/libgo/go/bytes/bytes_generic.go deleted file mode 100644 index b52d9396520..00000000000 --- a/libgo/go/bytes/bytes_generic.go +++ /dev/null @@ -1,65 +0,0 @@ -// 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. - -// -build !amd64,!s390x,!arm64 - -package bytes - -// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. -func Index(s, sep []byte) int { - n := len(sep) - switch { - case n == 0: - return 0 - case n == 1: - return IndexByte(s, sep[0]) - case n == len(s): - if Equal(sep, s) { - return 0 - } - return -1 - case n > len(s): - return -1 - } - c := sep[0] - i := 0 - fails := 0 - t := s[:len(s)-n+1] - for i < len(t) { - if t[i] != c { - o := IndexByte(t[i:], c) - if o < 0 { - break - } - i += o - } - if Equal(s[i:i+n], sep) { - return i - } - i++ - fails++ - if fails >= 4+i>>4 && i < len(t) { - // Give up on IndexByte, it isn't skipping ahead - // far enough to be better than Rabin-Karp. - // Experiments (using IndexPeriodic) suggest - // the cutover is about 16 byte skips. - // TODO: if large prefixes of sep are matching - // we should cutover at even larger average skips, - // because Equal becomes that much more expensive. - // This code does not take that effect into account. - j := indexRabinKarp(s[i:], sep) - if j < 0 { - return -1 - } - return i + j - } - } - return -1 -} - -// Count counts the number of non-overlapping instances of sep in s. -// If sep is an empty slice, Count returns 1 + the number of UTF-8-encoded code points in s. -func Count(s, sep []byte) int { - return countGeneric(s, sep) -} diff --git a/libgo/go/bytes/bytes_s390x.go b/libgo/go/bytes/bytes_s390x.go deleted file mode 100644 index 0c228486fc3..00000000000 --- a/libgo/go/bytes/bytes_s390x.go +++ /dev/null @@ -1,88 +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. - -// +build ignore - -package bytes - -//go:noescape - -// indexShortStr returns the index of the first instance of sep in s, -// or -1 if sep is not present in s. -// indexShortStr requires 2 <= len(sep) <= shortStringLen -func indexShortStr(s, c []byte) int // ../runtime/asm_s390x.s - -// supportsVX reports whether the vector facility is available. -// indexShortStr must not be called if the vector facility is not -// available. -func supportsVX() bool // ../runtime/asm_s390x.s - -var shortStringLen = -1 - -func init() { - if supportsVX() { - shortStringLen = 64 - } -} - -// Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. -func Index(s, sep []byte) int { - n := len(sep) - switch { - case n == 0: - return 0 - case n == 1: - return IndexByte(s, sep[0]) - case n == len(s): - if Equal(sep, s) { - return 0 - } - return -1 - case n > len(s): - return -1 - case n <= shortStringLen: - // Use brute force when s and sep both are small - if len(s) <= 64 { - return indexShortStr(s, sep) - } - c := sep[0] - i := 0 - t := s[:len(s)-n+1] - fails := 0 - for i < len(t) { - if t[i] != c { - // IndexByte skips 16/32 bytes per iteration, - // so it's faster than indexShortStr. - o := IndexByte(t[i:], c) - if o < 0 { - return -1 - } - i += o - } - if Equal(s[i:i+n], sep) { - return i - } - fails++ - i++ - // Switch to indexShortStr when IndexByte produces too many false positives. - // Too many means more that 1 error per 8 characters. - // Allow some errors in the beginning. - if fails > (i+16)/8 { - r := indexShortStr(s[i:], sep) - if r >= 0 { - return r + i - } - return -1 - } - } - return -1 - } - return indexRabinKarp(s, sep) -} - -// Count counts the number of non-overlapping instances of sep in s. -// If sep is an empty slice, Count returns 1 + the number of UTF-8-encoded code points in s. -func Count(s, sep []byte) int { - return countGeneric(s, sep) -} diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go index 23fce29e319..11c5ef9ab80 100644 --- a/libgo/go/bytes/bytes_test.go +++ b/libgo/go/bytes/bytes_test.go @@ -415,10 +415,6 @@ func TestCountByte(t *testing.T) { if p != j+1 { t.Errorf("TestCountByte.Count(%q, 100) = %d", b[i:i+window], p) } - pGeneric := CountGeneric(b[i:i+window], []byte{100}) - if pGeneric != j+1 { - t.Errorf("TestCountByte.CountGeneric(%q, 100) = %d", b[i:i+window], p) - } } } @@ -466,10 +462,6 @@ func TestCountByteNoMatch(t *testing.T) { if p != 0 { t.Errorf("TestCountByteNoMatch(%q, 0) = %d", b[i:i+window], p) } - pGeneric := CountGeneric(b[i:i+window], []byte{0}) - if pGeneric != 0 { - t.Errorf("TestCountByteNoMatch.CountGeneric(%q, 100) = %d", b[i:i+window], p) - } for j := 0; j < window; j++ { b[i+j] = byte(0) } diff --git a/libgo/go/bytes/compare_test.go b/libgo/go/bytes/compare_test.go index 35088a1b2e9..3e33c27c9c9 100644 --- a/libgo/go/bytes/compare_test.go +++ b/libgo/go/bytes/compare_test.go @@ -6,6 +6,7 @@ package bytes_test import ( . "bytes" + "internal/testenv" "testing" ) @@ -58,10 +59,20 @@ func TestCompareIdenticalSlice(t *testing.T) { } func TestCompareBytes(t *testing.T) { - n := 128 + lengths := make([]int, 0) // lengths to test in ascending order + for i := 0; i <= 128; i++ { + lengths = append(lengths, i) + } + lengths = append(lengths, 256, 512, 1024, 1333, 4095, 4096, 4097) + + if !testing.Short() || testenv.Builder() != "" { + lengths = append(lengths, 65535, 65536, 65537, 99999) + } + + n := lengths[len(lengths)-1] a := make([]byte, n+1) b := make([]byte, n+1) - for len := 0; len < 128; len++ { + for _, len := range lengths { // randomish but deterministic data. No 0 or 255. for i := 0; i < len; i++ { a[i] = byte(1 + 31*i%254) diff --git a/libgo/go/bytes/export_test.go b/libgo/go/bytes/export_test.go index 823c8b09eef..f61523e60bb 100644 --- a/libgo/go/bytes/export_test.go +++ b/libgo/go/bytes/export_test.go @@ -7,4 +7,3 @@ package bytes // Export func for testing var IndexBytePortable = indexBytePortable var EqualPortable = equalPortable -var CountGeneric = countGeneric diff --git a/libgo/go/cmd/buildid/buildid.go b/libgo/go/cmd/buildid/buildid.go index 8d810ffdd99..1c7b228c987 100644 --- a/libgo/go/cmd/buildid/buildid.go +++ b/libgo/go/cmd/buildid/buildid.go @@ -22,6 +22,21 @@ func usage() { var wflag = flag.Bool("w", false, "write build ID") +// taken from cmd/go/internal/work/buildid.go +func hashToString(h [32]byte) string { + const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" + const chunks = 5 + var dst [chunks * 4]byte + for i := 0; i < chunks; i++ { + v := uint32(h[3*i])<<16 | uint32(h[3*i+1])<<8 | uint32(h[3*i+2]) + dst[4*i+0] = b64[(v>>18)&0x3F] + dst[4*i+1] = b64[(v>>12)&0x3F] + dst[4*i+2] = b64[(v>>6)&0x3F] + dst[4*i+3] = b64[v&0x3F] + } + return string(dst[:]) +} + func main() { log.SetPrefix("buildid: ") log.SetFlags(0) @@ -41,6 +56,8 @@ func main() { return } + // Keep in sync with src/cmd/go/internal/work/buildid.go:updateBuildID + f, err := os.Open(file) if err != nil { log.Fatal(err) @@ -51,14 +68,14 @@ func main() { } f.Close() - tail := id - if i := strings.LastIndex(id, "."); i >= 0 { - tail = tail[i+1:] + newID := id[:strings.LastIndex(id, "/")] + "/" + hashToString(hash) + if len(newID) != len(id) { + log.Fatalf("%s: build ID length mismatch %q vs %q", file, id, newID) } - if len(tail) != len(hash)*2 { - log.Fatalf("%s: cannot find %d-byte hash in id %s", file, len(hash), id) + + if len(matches) == 0 { + return } - newID := id[:len(id)-len(tail)] + fmt.Sprintf("%x", hash) f, err = os.OpenFile(file, os.O_WRONLY, 0) if err != nil { diff --git a/libgo/go/cmd/cgo/ast.go b/libgo/go/cmd/cgo/ast.go index 58e0ee78cb7..4462136bf4b 100644 --- a/libgo/go/cmd/cgo/ast.go +++ b/libgo/go/cmd/cgo/ast.go @@ -95,7 +95,7 @@ func (f *File) ParseGo(name string, src []byte) { } } if !sawC { - error_(token.NoPos, `cannot find import "C"`) + error_(ast1.Package, `cannot find import "C"`) } // In ast2, strip the import "C" line. @@ -356,6 +356,7 @@ func (f *File) walk(x interface{}, context astContext, visit func(*File, interfa case *ast.BadExpr: case *ast.Ident: case *ast.Ellipsis: + f.walk(&n.Elt, ctxType, visit) case *ast.BasicLit: case *ast.FuncLit: f.walk(n.Type, ctxType, visit) diff --git a/libgo/go/cmd/cgo/doc.go b/libgo/go/cmd/cgo/doc.go index c16b63a313b..157cd94d653 100644 --- a/libgo/go/cmd/cgo/doc.go +++ b/libgo/go/cmd/cgo/doc.go @@ -64,6 +64,11 @@ a full argument: to allow -mfoo=bar, use CGO_CFLAGS_ALLOW='-mfoo.*', not just CGO_CFLAGS_ALLOW='-mfoo'. Similarly named variables control the allowed CPPFLAGS, CXXFLAGS, FFLAGS, and LDFLAGS. +Also for security reasons, only a limited set of characters are +permitted, notably alphanumeric characters and a few symbols, such as +'.', that will not be interpreted in unexpected ways. Attempts to use +forbidden characters will get a "malformed #cgo argument" error. + When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS, CGO_FFLAGS and CGO_LDFLAGS environment variables are added to the flags derived from these directives. Package-specific flags should be set using the @@ -99,17 +104,24 @@ compiled with the C compiler. Any .cc, .cpp, or .cxx files will be compiled with the C++ compiler. Any .f, .F, .for or .f90 files will be compiled with the fortran compiler. Any .h, .hh, .hpp, or .hxx files will not be compiled separately, but, if these header files are changed, -the C and C++ files will be recompiled. The default C and C++ -compilers may be changed by the CC and CXX environment variables, -respectively; those environment variables may include command line -options. +the package (including its non-Go source files) will be recompiled. +Note that changes to files in other directories do not cause the package +to be recompiled, so all non-Go source code for the package should be +stored in the package directory, not in subdirectories. +The default C and C++ compilers may be changed by the CC and CXX +environment variables, respectively; those environment variables +may include command line options. The cgo tool is enabled by default for native builds on systems where it is expected to work. It is disabled by default when cross-compiling. You can control this by setting the CGO_ENABLED environment variable when running the go tool: set it to 1 to enable the use of cgo, and to 0 to disable it. The go tool will set the -build constraint "cgo" if cgo is enabled. +build constraint "cgo" if cgo is enabled. The special import "C" +implies the "cgo" build constraint, as though the file also said +"// +build cgo". Therefore, if cgo is disabled, files that import +"C" will not be built by the go tool. (For more about build constraints +see https://golang.org/pkg/go/build/#hdr-Build_Constraints). When cross-compiling, you must specify a C cross-compiler for cgo to use. You can do this by setting the generic CC_FOR_TARGET or the @@ -219,6 +231,26 @@ C compilers are aware of this calling convention and adjust the call accordingly, but Go cannot. In Go, you must pass the pointer to the first element explicitly: C.f(&C.x[0]). +Calling variadic C functions is not supported. It is possible to +circumvent this by using a C function wrapper. For example: + + package main + + // #include + // #include + // + // static void myprint(char* s) { + // printf("%s\n", s); + // } + import "C" + import "unsafe" + + func main() { + cs := C.CString("Hello from stdio") + C.myprint(cs) + C.free(unsafe.Pointer(cs)) + } + A few special functions convert between Go and C types by making copies of the data. In pseudo-Go definitions: @@ -348,6 +380,14 @@ 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. +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 +contents of the C memory appear to be a Go pointer. Therefore, avoid +passing uninitialized C memory to Go code if the Go code is going to +store pointer values in it. Zero out the memory in C before passing it +to Go. + Special cases A few special C types which would normally be represented by a pointer diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go index 534fba17eb4..2a2d0080d5e 100644 --- a/libgo/go/cmd/cgo/gcc.go +++ b/libgo/go/cmd/cgo/gcc.go @@ -183,9 +183,29 @@ func (p *Package) Translate(f *File) { cref.Name.C = cname(cref.Name.Go) } p.loadDefines(f) - needType := p.guessKinds(f) - if len(needType) > 0 { - p.loadDWARF(f, needType) + p.typedefs = map[string]bool{} + p.typedefList = nil + numTypedefs := -1 + for len(p.typedefs) > numTypedefs { + numTypedefs = len(p.typedefs) + // Also ask about any typedefs we've seen so far. + for _, a := range p.typedefList { + f.Name[a] = &Name{ + Go: a, + C: a, + } + } + needType := p.guessKinds(f) + if len(needType) > 0 { + p.loadDWARF(f, needType) + } + + // In godefs mode we're OK with the typedefs, which + // will presumably also be defined in the file, we + // don't want to resolve them to their base types. + if *godefs { + break + } } if p.rewriteCalls(f) { // Add `import _cgo_unsafe "unsafe"` after the package statement. @@ -570,6 +590,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) { fatalf("malformed __cgo__ name: %s", name) } types[i] = t.Type + p.recordTypedefs(t.Type) } if e.Tag != dwarf.TagCompileUnit { r.SkipChildren() @@ -605,7 +626,25 @@ func (p *Package) loadDWARF(f *File, names []*Name) { } } case "fconst": - if i < len(floats) { + if i >= len(floats) { + break + } + switch base(types[i]).(type) { + case *dwarf.IntType, *dwarf.UintType: + // This has an integer type so it's + // not really a floating point + // constant. This can happen when the + // C compiler complains about using + // the value as an integer constant, + // but not as a general constant. + // Treat this as a variable of the + // appropriate type, not a constant, + // to get C-style type handling, + // avoiding the problem that C permits + // uint64(-1) but Go does not. + // See issue 26066. + n.Kind = "var" + default: n.Const = fmt.Sprintf("%f", floats[i]) } case "sconst": @@ -618,6 +657,47 @@ func (p *Package) loadDWARF(f *File, names []*Name) { } } +// recordTypedefs remembers in p.typedefs all the typedefs used in dtypes and its children. +func (p *Package) recordTypedefs(dtype dwarf.Type) { + p.recordTypedefs1(dtype, map[dwarf.Type]bool{}) +} +func (p *Package) recordTypedefs1(dtype dwarf.Type, visited map[dwarf.Type]bool) { + if dtype == nil { + return + } + if visited[dtype] { + return + } + visited[dtype] = true + switch dt := dtype.(type) { + case *dwarf.TypedefType: + if strings.HasPrefix(dt.Name, "__builtin") { + // Don't look inside builtin types. There be dragons. + return + } + if !p.typedefs[dt.Name] { + p.typedefs[dt.Name] = true + p.typedefList = append(p.typedefList, dt.Name) + p.recordTypedefs1(dt.Type, visited) + } + case *dwarf.PtrType: + p.recordTypedefs1(dt.Type, visited) + case *dwarf.ArrayType: + p.recordTypedefs1(dt.Type, visited) + case *dwarf.QualType: + p.recordTypedefs1(dt.Type, visited) + case *dwarf.FuncType: + p.recordTypedefs1(dt.ReturnType, visited) + for _, a := range dt.ParamType { + p.recordTypedefs1(a, visited) + } + case *dwarf.StructType: + for _, f := range dt.Field { + p.recordTypedefs1(f.Type, visited) + } + } +} + // mangleName does name mangling to translate names // from the original Go source files to the names // used in the final Go files generated by cgo. @@ -1373,7 +1453,7 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6 if len(data) <= strlen { fatalf("invalid string literal") } - strs[n] = string(data[:strlen]) + strs[n] = data[:strlen] } } @@ -1754,6 +1834,7 @@ type typeConv struct { // Map from types to incomplete pointers to those types. ptrs map[dwarf.Type][]*Type // Keys of ptrs in insertion order (deterministic worklist) + // ptrKeys contains exactly the keys in ptrs. ptrKeys []dwarf.Type // Type names X for which there exists an XGetTypeID function with type func() CFTypeID. @@ -1896,14 +1977,15 @@ func (c *typeConv) FinishType(pos token.Pos) { for len(c.ptrKeys) > 0 { dtype := c.ptrKeys[0] c.ptrKeys = c.ptrKeys[1:] + ptrs := c.ptrs[dtype] + delete(c.ptrs, dtype) // Note Type might invalidate c.ptrs[dtype]. t := c.Type(dtype, pos) - for _, ptr := range c.ptrs[dtype] { + for _, ptr := range ptrs { ptr.Go.(*ast.StarExpr).X = t.Go ptr.C.Set("%s*", t.C) } - c.ptrs[dtype] = nil // retain the map key } } @@ -2180,6 +2262,10 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { s := *sub s.Go = c.uintptr sub = &s + // Make sure we update any previously computed type. + if oldType := typedef[name.Name]; oldType != nil { + oldType.Go = sub.Go + } } t.Go = name if unionWithPointer[sub.Go] { @@ -2341,7 +2427,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type { } // ...or the typedef is one in which we expect bad pointers. // It will be a uintptr instead of *X. - if c.badPointerTypedef(dt) { + if c.baseBadPointerTypedef(dt) { break } @@ -2693,6 +2779,19 @@ func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool { return false } +// baseBadPointerTypedef reports whether the base of a chain of typedefs is a bad typedef +// as badPointerTypedef reports. +func (c *typeConv) baseBadPointerTypedef(dt *dwarf.TypedefType) bool { + for { + if t, ok := dt.Type.(*dwarf.TypedefType); ok { + dt = t + continue + } + break + } + return c.badPointerTypedef(dt) +} + func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool { // The real bad types are CFNumberRef and CFDateRef. // Sometimes non-pointers are stored in these types. @@ -2781,13 +2880,31 @@ func (c *typeConv) badJNI(dt *dwarf.TypedefType) bool { } } - // Check that the typedef is: - // struct _jobject; - // typedef struct _jobject *jobject; + // Check that the typedef is either: + // 1: + // struct _jobject; + // typedef struct _jobject *jobject; + // 2: (in NDK16 in C++) + // class _jobject {}; + // typedef _jobject* jobject; + // 3: (in NDK16 in C) + // typedef void* jobject; if ptr, ok := w.Type.(*dwarf.PtrType); ok { - if str, ok := ptr.Type.(*dwarf.StructType); ok { - if str.StructName == "_jobject" && str.Kind == "struct" && len(str.Field) == 0 && str.Incomplete { - return true + switch v := ptr.Type.(type) { + case *dwarf.VoidType: + return true + case *dwarf.StructType: + if v.StructName == "_jobject" && len(v.Field) == 0 { + switch v.Kind { + case "struct": + if v.Incomplete { + return true + } + case "class": + if !v.Incomplete { + return true + } + } } } } @@ -2796,7 +2913,7 @@ func (c *typeConv) badJNI(dt *dwarf.TypedefType) bool { } // jniTypes maps from JNI types that we want to be uintptrs, to the underlying type to which -// they are mapped. The base "jobject" maps to the empty string. +// they are mapped. The base "jobject" maps to the empty string. var jniTypes = map[string]string{ "jobject": "", "jclass": "jobject", diff --git a/libgo/go/cmd/cgo/godefs.go b/libgo/go/cmd/cgo/godefs.go index 6d638f06442..6720945cddd 100644 --- a/libgo/go/cmd/cgo/godefs.go +++ b/libgo/go/cmd/cgo/godefs.go @@ -19,7 +19,7 @@ import ( func (p *Package) godefs(f *File, srcfile string) string { var buf bytes.Buffer - fmt.Fprintf(&buf, "// Created by cgo -godefs - DO NOT EDIT\n") + fmt.Fprintf(&buf, "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n") fmt.Fprintf(&buf, "// %s %s\n", filepath.Base(os.Args[0]), strings.Join(os.Args[1:], " ")) fmt.Fprintf(&buf, "\n") diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go index 890a365ceef..1238016418e 100644 --- a/libgo/go/cmd/cgo/main.go +++ b/libgo/go/cmd/cgo/main.go @@ -17,6 +17,7 @@ import ( "go/ast" "go/printer" "go/token" + "io" "io/ioutil" "os" "path/filepath" @@ -42,9 +43,11 @@ type Package struct { Name map[string]*Name // accumulated Name from Files ExpFunc []*ExpFunc // accumulated ExpFunc from Files Decl []ast.Decl - GoFiles []string // list of Go files - GccFiles []string // list of gcc output files - Preamble string // collected preamble for _cgo_export.h + GoFiles []string // list of Go files + GccFiles []string // list of gcc output files + Preamble string // collected preamble for _cgo_export.h + typedefs map[string]bool // type names that appear in the types of the objects we're interested in + typedefList []string } // A File collects information about a single Go input file. @@ -278,6 +281,9 @@ func main() { if arg == "-fsanitize=thread" { tsanProlog = yesTsanProlog } + if arg == "-fsanitize=memory" { + msanProlog = yesMsanProlog + } } p := newPackage(args[:i]) @@ -297,6 +303,7 @@ func main() { // concern is other cgo wrappers for the same functions. // Use the beginning of the md5 of the input to disambiguate. h := md5.New() + io.WriteString(h, *importPath) fs := make([]*File, len(goFiles)) for i, input := range goFiles { if *srcDir != "" { @@ -410,6 +417,14 @@ func (p *Package) Record(f *File) { for k, v := range f.Name { if p.Name[k] == nil { p.Name[k] = v + } else if p.incompleteTypedef(p.Name[k].Type) { + p.Name[k] = v + } else if p.incompleteTypedef(v.Type) { + // Nothing to do. + } else if _, ok := nameToC[k]; ok { + // Names we predefine may appear inconsistent + // if some files typedef them and some don't. + // Issue 26743. } else if !reflect.DeepEqual(p.Name[k], v) { error_(token.NoPos, "inconsistent definitions for C.%s", fixGo(k)) } @@ -422,3 +437,9 @@ func (p *Package) Record(f *File) { } p.Decl = append(p.Decl, f.AST.Decls...) } + +// incompleteTypedef reports whether t appears to be an incomplete +// typedef definition. +func (p *Package) incompleteTypedef(t *Type) bool { + return t == nil || (t.Size == 0 && t.Align == -1) +} diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go index 92fad5d31a7..10d4b74b6ee 100644 --- a/libgo/go/cmd/cgo/out.go +++ b/libgo/go/cmd/cgo/out.go @@ -17,6 +17,7 @@ import ( "io" "os" "path/filepath" + "regexp" "sort" "strings" ) @@ -78,7 +79,7 @@ func (p *Package) writeDefs() { // Write second Go output: definitions of _C_xxx. // In a separate file so that the import of "unsafe" does not // pollute the original file. - fmt.Fprintf(fgo2, "// Created by cgo - DO NOT EDIT\n\n") + fmt.Fprintf(fgo2, "// Code generated by cmd/cgo; DO NOT EDIT.\n\n") fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName) fmt.Fprintf(fgo2, "import \"unsafe\"\n\n") if !*gccgo && *importRuntimeCgo { @@ -277,10 +278,7 @@ func dynimport(obj string) { } } } - sym, err := f.ImportedSymbols() - if err != nil { - fatalf("cannot load imported symbols from ELF file %s: %v", obj, err) - } + sym, _ := f.ImportedSymbols() for _, s := range sym { targ := s.Name if s.Version != "" { @@ -288,10 +286,7 @@ func dynimport(obj string) { } fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library) } - lib, err := f.ImportedLibraries() - if err != nil { - fatalf("cannot load imported libraries from ELF file %s: %v", obj, err) - } + lib, _ := f.ImportedLibraries() for _, l := range lib { fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l) } @@ -299,20 +294,14 @@ func dynimport(obj string) { } if f, err := macho.Open(obj); err == nil { - sym, err := f.ImportedSymbols() - if err != nil { - fatalf("cannot load imported symbols from Mach-O file %s: %v", obj, err) - } + sym, _ := f.ImportedSymbols() for _, s := range sym { if len(s) > 0 && s[0] == '_' { s = s[1:] } fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "") } - lib, err := f.ImportedLibraries() - if err != nil { - fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err) - } + lib, _ := f.ImportedLibraries() for _, l := range lib { fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l) } @@ -320,10 +309,7 @@ func dynimport(obj string) { } if f, err := pe.Open(obj); err == nil { - sym, err := f.ImportedSymbols() - if err != nil { - fatalf("cannot load imported symbols from PE file %s: %v", obj, err) - } + sym, _ := f.ImportedSymbols() for _, s := range sym { ss := strings.Split(s, ":") name := strings.Split(ss[0], "@")[0] @@ -559,8 +545,8 @@ func (p *Package) writeOutput(f *File, srcfile string) { p.GccFiles = append(p.GccFiles, base+".cgo2.c") // Write Go output: Go input with rewrites of C.xxx to _C_xxx. - fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n") - fmt.Fprintf(fgo1, "//line %s:1\n", srcfile) + fmt.Fprintf(fgo1, "// Code generated by cmd/cgo; DO NOT EDIT.\n\n") + fmt.Fprintf(fgo1, "//line %s:1:1\n", srcfile) fgo1.Write(f.Edit.Bytes()) // While we process the vars and funcs, also write gcc output. @@ -569,6 +555,7 @@ func (p *Package) writeOutput(f *File, srcfile string) { fmt.Fprintf(fgcc, "%s\n", f.Preamble) fmt.Fprintf(fgcc, "%s\n", gccProlog) fmt.Fprintf(fgcc, "%s\n", tsanProlog) + fmt.Fprintf(fgcc, "%s\n", msanProlog) for _, key := range nameKeys(f.Name) { n := f.Name[key] @@ -632,14 +619,14 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { // We're trying to write a gcc struct that matches gc's layout. // Use packed attribute to force no padding in this struct in case // gcc has different packing requirements. - fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute()) + fmt.Fprintf(fgcc, "\t%s %v *_cgo_a = v;\n", ctype, p.packedAttribute()) if n.FuncType.Result != nil { // Save the stack top for use below. - fmt.Fprintf(fgcc, "\tchar *stktop = _cgo_topofstack();\n") + fmt.Fprintf(fgcc, "\tchar *_cgo_stktop = _cgo_topofstack();\n") } tr := n.FuncType.Result if tr != nil { - fmt.Fprintf(fgcc, "\t__typeof__(a->r) r;\n") + fmt.Fprintf(fgcc, "\t__typeof__(_cgo_a->r) _cgo_r;\n") } fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n") if n.AddError { @@ -647,9 +634,9 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { } fmt.Fprintf(fgcc, "\t") if tr != nil { - fmt.Fprintf(fgcc, "r = ") + fmt.Fprintf(fgcc, "_cgo_r = ") if c := tr.C.String(); c[len(c)-1] == '*' { - fmt.Fprint(fgcc, "(__typeof__(a->r)) ") + fmt.Fprint(fgcc, "(__typeof__(_cgo_a->r)) ") } } if n.Kind == "macro" { @@ -660,7 +647,7 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { if i > 0 { fmt.Fprintf(fgcc, ", ") } - fmt.Fprintf(fgcc, "a->p%d", i) + fmt.Fprintf(fgcc, "_cgo_a->p%d", i) } fmt.Fprintf(fgcc, ");\n") } @@ -671,9 +658,19 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { if n.FuncType.Result != nil { // The cgo call may have caused a stack copy (via a callback). // Adjust the return value pointer appropriately. - fmt.Fprintf(fgcc, "\ta = (void*)((char*)a + (_cgo_topofstack() - stktop));\n") + fmt.Fprintf(fgcc, "\t_cgo_a = (void*)((char*)_cgo_a + (_cgo_topofstack() - _cgo_stktop));\n") // Save the return value. - fmt.Fprintf(fgcc, "\ta->r = r;\n") + fmt.Fprintf(fgcc, "\t_cgo_a->r = _cgo_r;\n") + // The return value is on the Go stack. If we are using msan, + // and if the C value is partially or completely uninitialized, + // the assignment will mark the Go stack as uninitialized. + // The Go compiler does not update msan for changes to the + // stack. It is possible that the stack will remain + // uninitialized, and then later be used in a way that is + // visible to msan, possibly leading to a false positive. + // Mark the stack space as written, to avoid this problem. + // See issue 26209. + fmt.Fprintf(fgcc, "\t_cgo_msan_write(&_cgo_a->r, sizeof(_cgo_a->r));\n") } if n.AddError { fmt.Fprintf(fgcc, "\treturn _cgo_errno;\n") @@ -708,12 +705,12 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) { fmt.Fprintf(fgcc, ")\n") fmt.Fprintf(fgcc, "{\n") if t := n.FuncType.Result; t != nil { - fmt.Fprintf(fgcc, "\t%s r;\n", t.C.String()) + fmt.Fprintf(fgcc, "\t%s _cgo_r;\n", t.C.String()) } fmt.Fprintf(fgcc, "\t_cgo_tsan_acquire();\n") fmt.Fprintf(fgcc, "\t") if t := n.FuncType.Result; t != nil { - fmt.Fprintf(fgcc, "r = ") + fmt.Fprintf(fgcc, "_cgo_r = ") // Cast to void* to avoid warnings due to omitted qualifiers. if c := t.C.String(); c[len(c)-1] == '*' { fmt.Fprintf(fgcc, "(void*)") @@ -739,7 +736,7 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) { if c := t.C.String(); c[len(c)-1] == '*' { fmt.Fprintf(fgcc, "(void*)") } - fmt.Fprintf(fgcc, "r;\n") + fmt.Fprintf(fgcc, "_cgo_r;\n") } fmt.Fprintf(fgcc, "}\n") fmt.Fprintf(fgcc, "\n") @@ -748,7 +745,7 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) { // packedAttribute returns host compiler struct attribute that will be // used to match gc's struct layout. For example, on 386 Windows, // gcc wants to 8-align int64s, but gc does not. -// Use __gcc_struct__ to work around http://gcc.gnu.org/PR52991 on x86, +// Use __gcc_struct__ to work around https://gcc.gnu.org/PR52991 on x86, // and https://golang.org/issue/5603. func (p *Package) packedAttribute() string { s := "__attribute__((__packed__" @@ -763,7 +760,7 @@ func (p *Package) packedAttribute() string { func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) { p.writeExportHeader(fgcch) - fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") + fmt.Fprintf(fgcc, "/* Code generated by cmd/cgo; DO NOT EDIT. */\n\n") fmt.Fprintf(fgcc, "#include \n") fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n\n") @@ -772,6 +769,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) { fmt.Fprintf(fgcc, "extern void _cgo_release_context(__SIZE_TYPE__);\n\n") fmt.Fprintf(fgcc, "extern char* _cgo_topofstack(void);") fmt.Fprintf(fgcc, "%s\n", tsanProlog) + fmt.Fprintf(fgcc, "%s\n", msanProlog) for _, exp := range p.ExpFunc { fn := exp.Func @@ -1004,11 +1002,12 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) { p.writeExportHeader(fgcch) - fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") + fmt.Fprintf(fgcc, "/* Code generated by cmd/cgo; DO NOT EDIT. */\n\n") fmt.Fprintf(fgcc, "#include \"_cgo_export.h\"\n") fmt.Fprintf(fgcc, "%s\n", gccgoExportFileProlog) fmt.Fprintf(fgcc, "%s\n", tsanProlog) + fmt.Fprintf(fgcc, "%s\n", msanProlog) for _, exp := range p.ExpFunc { fn := exp.Func @@ -1170,7 +1169,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) { // writeExportHeader writes out the start of the _cgo_export.h file. func (p *Package) writeExportHeader(fgcch io.Writer) { - fmt.Fprintf(fgcch, "/* Created by \"go tool cgo\" - DO NOT EDIT. */\n\n") + fmt.Fprintf(fgcch, "/* Code generated by cmd/cgo; DO NOT EDIT. */\n\n") pkg := *importPath if pkg == "" { pkg = p.PackagePath @@ -1178,8 +1177,15 @@ func (p *Package) writeExportHeader(fgcch io.Writer) { fmt.Fprintf(fgcch, "/* package %s */\n\n", pkg) fmt.Fprintf(fgcch, "%s\n", builtinExportProlog) + // Remove absolute paths from #line comments in the preamble. + // They aren't useful for people using the header file, + // and they mean that the header files change based on the + // exact location of GOPATH. + re := regexp.MustCompile(`(?m)^(#line\s+[0-9]+\s+")[^"]*[/\\]([^"]*")`) + preamble := re.ReplaceAllString(p.Preamble, "$1$2") + fmt.Fprintf(fgcch, "/* Start of preamble from import \"C\" comments. */\n\n") - fmt.Fprintf(fgcch, "%s\n", p.Preamble) + fmt.Fprintf(fgcch, "%s\n", preamble) fmt.Fprintf(fgcch, "\n/* End of preamble from import \"C\" comments. */\n\n") fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog()) @@ -1414,6 +1420,25 @@ static void _cgo_tsan_release() { // Set to yesTsanProlog if we see -fsanitize=thread in the flags for gcc. var tsanProlog = noTsanProlog +// noMsanProlog is a prologue defining an MSAN function in C. +// This is used when not compiling with -fsanitize=memory. +const noMsanProlog = ` +#define _cgo_msan_write(addr, sz) +` + +// yesMsanProlog is a prologue defining an MSAN function in C. +// This is used when compiling with -fsanitize=memory. +// See the comment above where _cgo_msan_write is called. +const yesMsanProlog = ` +extern void __msan_unpoison(const volatile void *, size_t); + +#define _cgo_msan_write(addr, sz) __msan_unpoison((addr), (sz)) +` + +// msanProlog is set to yesMsanProlog if we see -fsanitize=memory in the flags +// for the C compiler. +var msanProlog = noMsanProlog + const builtinProlog = ` #line 1 "cgo-builtin-prolog" #include /* for ptrdiff_t and size_t below */ diff --git a/libgo/go/cmd/cgo/util.go b/libgo/go/cmd/cgo/util.go index 4f5c48864e9..921306b7aab 100644 --- a/libgo/go/cmd/cgo/util.go +++ b/libgo/go/cmd/cgo/util.go @@ -59,6 +59,8 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) { var bout, berr bytes.Buffer p.Stdout = &bout p.Stderr = &berr + // Disable escape codes in clang error messages. + p.Env = append(os.Environ(), "TERM=dumb") err := p.Run() if _, ok := err.(*exec.ExitError); err != nil && !ok { fatalf("%s", err) @@ -97,6 +99,8 @@ func error_(pos token.Pos, msg string, args ...interface{}) { nerrors++ if pos.IsValid() { fmt.Fprintf(os.Stderr, "%s: ", fset.Position(pos).String()) + } else { + fmt.Fprintf(os.Stderr, "cgo: ") } fmt.Fprintf(os.Stderr, msg, args...) fmt.Fprintf(os.Stderr, "\n") diff --git a/libgo/go/cmd/go/alldocs.go b/libgo/go/cmd/go/alldocs.go index aadf97c064f..ebbd154f3e6 100644 --- a/libgo/go/cmd/go/alldocs.go +++ b/libgo/go/cmd/go/alldocs.go @@ -2,50 +2,66 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh. +// Code generated by mkalldocs.sh; DO NOT EDIT. // Edit the documentation in other files and rerun mkalldocs.sh to generate this one. // Go is a tool for managing Go source code. // // Usage: // -// go command [arguments] +// go [arguments] // // The commands are: // +// bug start a bug report // build compile packages and dependencies // clean remove object files and cached files // doc show documentation for package or symbol // env print Go environment information -// bug start a bug report // fix update packages to use new APIs // fmt gofmt (reformat) package sources // generate generate Go files by processing source // get download and install packages and dependencies // install compile and install packages and dependencies -// list list packages +// list list packages or modules +// mod module maintenance // run compile and run Go program // test test packages // tool run specified go tool // version print Go version // vet report likely mistakes in packages // -// Use "go help [command]" for more information about a command. +// Use "go help " for more information about a command. // // Additional help topics: // -// c calling between Go and C // buildmode build modes +// c calling between Go and C // cache build and test caching -// filetype file types -// gopath GOPATH environment variable // environment environment variables +// filetype file types +// go.mod the go.mod file +// gopath GOPATH environment variable +// gopath-get legacy GOPATH go get +// goproxy module proxy protocol // importpath import path syntax -// packages package lists +// modules modules, module versions, and more +// module-get module-aware go get +// packages package lists and patterns // testflag testing flags // testfunc testing functions // -// Use "go help [topic]" for more information about that topic. +// Use "go help " for more information about that topic. +// +// +// Start a bug report +// +// Usage: +// +// go bug +// +// Bug opens the default browser and starts a new bug report. +// The report includes useful system information. // // // Compile packages and dependencies @@ -95,7 +111,7 @@ // Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. // -msan // enable interoperation with memory sanitizer. -// Supported only on linux/amd64, +// Supported only on linux/amd64, linux/arm64 // and only with Clang/LLVM as the host C compiler. // -v // print the names of packages as they are compiled. @@ -127,6 +143,9 @@ // -linkshared // link against shared libraries previously created with // -buildmode=shared. +// -mod mode +// module download mode to use: readonly, release, or vendor. +// See 'go help modules' for more. // -pkgdir dir // install and load all packages from dir instead of the usual locations. // For example, when building with a non-standard configuration, @@ -175,7 +194,7 @@ // // Usage: // -// go clean [-i] [-r] [-n] [-x] [-cache] [-testcache] [build flags] [packages] +// go clean [clean flags] [build flags] [packages] // // Clean removes object files from package source directories. // The go command builds most objects in a temporary directory, @@ -218,6 +237,10 @@ // The -testcache flag causes clean to expire all test results in the // go build cache. // +// The -modcache flag causes clean to remove the entire module +// download cache, including unpacked source code of versioned +// dependencies. +// // For more about build flags, see 'go help build'. // // For more about specifying packages, see 'go help packages'. @@ -349,16 +372,6 @@ // For more about environment variables, see 'go help environment'. // // -// Start a bug report -// -// Usage: -// -// go bug -// -// Bug opens the default browser and starts a new bug report. -// The report includes useful system information. -// -// // Update packages to use new APIs // // Usage: @@ -419,6 +432,12 @@ // (gofmt), a fully qualified path (/usr/you/bin/mytool), or a // command alias, described below. // +// To convey to humans and machine tools that code is generated, +// generated source should have a line early in the file that +// matches the following regular expression (in Go syntax): +// +// ^// Code generated .* DO NOT EDIT\.$ +// // Note that go generate does not parse the file, so lines that look // like directives in comments or multiline strings will be treated // as directives. @@ -506,7 +525,7 @@ // // Usage: // -// go get [-d] [-f] [-fix] [-insecure] [-t] [-u] [-v] [build flags] [packages] +// go get [-d] [-f] [-t] [-u] [-v] [-fix] [-insecure] [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'. @@ -556,6 +575,12 @@ // For more about how 'go get' finds source code to // download, see 'go help importpath'. // +// This text describes the behavior of get when using GOPATH +// to manage source code and dependencies. +// If instead the go command is running in module-aware mode, +// the details of get's flags and effects change, as does 'go help get'. +// See 'go help modules' and 'go help module-get'. +// // See also: go build, go install, go clean. // // @@ -575,13 +600,16 @@ // See also: go build, go get, go clean. // // -// List packages +// List packages or modules // // Usage: // -// go list [-e] [-f format] [-json] [build flags] [packages] +// go list [-f format] [-json] [-m] [list flags] [build flags] [packages] // -// List lists the packages named by the import paths, one per line. +// List lists the named packages, one per line. +// The most commonly-used flags are -f and -json, which control the form +// of the output printed for each package. Other list flags, documented below, +// control more specific details. // // The default output shows the package import path: // @@ -591,40 +619,46 @@ // golang.org/x/net/html // // The -f flag specifies an alternate format for the list, using the -// syntax of package template. The default output is equivalent to -f -// '{{.ImportPath}}'. The struct being passed to the template is: +// syntax of package template. The default output is equivalent +// to -f '{{.ImportPath}}'. The struct being passed to the template is: // // type Package struct { -// Dir string // directory containing package sources -// ImportPath string // import path of package in dir -// ImportComment string // path in import comment on package statement -// Name string // package name -// Doc string // package documentation string -// Target string // install path -// Shlib string // the shared library that contains this package (only set when -linkshared) -// Goroot bool // is this package in the Go root? -// Standard bool // is this package part of the standard Go library? -// Stale bool // would 'go install' do anything for this package? -// StaleReason string // explanation for Stale==true -// Root string // Go root or Go path dir containing this package -// ConflictDir string // this directory shadows Dir in $GOPATH -// BinaryOnly bool // binary-only package: cannot be recompiled from sources +// Dir string // directory containing package sources +// ImportPath string // import path of package in dir +// ImportComment string // path in import comment on package statement +// Name string // package name +// Doc string // package documentation string +// Target string // install path +// Shlib string // the shared library that contains this package (only set when -linkshared) +// Goroot bool // is this package in the Go root? +// Standard bool // is this package part of the standard Go library? +// Stale bool // would 'go install' do anything for this package? +// StaleReason string // explanation for Stale==true +// Root string // Go root or Go path dir containing this package +// ConflictDir string // this directory shadows Dir in $GOPATH +// BinaryOnly bool // binary-only package: cannot be recompiled from sources +// ForTest string // package is only for use in named test +// Export string // file containing export data (when using -export) +// Module *Module // info about package's containing module, if any (can be nil) +// Match []string // command-line patterns matching this package +// DepOnly bool // package is only a dependency, not explicitly listed // // // Source files -// GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) -// CgoFiles []string // .go sources files that import "C" -// IgnoredGoFiles []string // .go sources ignored due to build constraints -// CFiles []string // .c source files -// CXXFiles []string // .cc, .cxx and .cpp source files -// MFiles []string // .m source files -// HFiles []string // .h, .hh, .hpp and .hxx source files -// FFiles []string // .f, .F, .for and .f90 Fortran source files -// SFiles []string // .s source files -// SwigFiles []string // .swig files -// SwigCXXFiles []string // .swigcxx files -// SysoFiles []string // .syso object files to add to archive -// TestGoFiles []string // _test.go files in package -// XTestGoFiles []string // _test.go files outside package +// GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) +// CgoFiles []string // .go source files that import "C" +// CompiledGoFiles []string // .go files presented to compiler (when using -compiled) +// IgnoredGoFiles []string // .go source files ignored due to build constraints +// CFiles []string // .c source files +// CXXFiles []string // .cc, .cxx and .cpp source files +// MFiles []string // .m source files +// HFiles []string // .h, .hh, .hpp and .hxx source files +// FFiles []string // .f, .F, .for and .f90 Fortran source files +// SFiles []string // .s source files +// SwigFiles []string // .swig files +// SwigCXXFiles []string // .swigcxx files +// SysoFiles []string // .syso object files to add to archive +// TestGoFiles []string // _test.go files in package +// XTestGoFiles []string // _test.go files outside package // // // Cgo directives // CgoCFLAGS []string // cgo: flags for C compiler @@ -635,10 +669,11 @@ // CgoPkgConfig []string // cgo: pkg-config names // // // Dependency information -// Imports []string // import paths used by this package -// Deps []string // all (recursively) imported dependencies -// TestImports []string // imports from TestGoFiles -// XTestImports []string // imports from XTestGoFiles +// Imports []string // import paths used by this package +// ImportMap map[string]string // map from source import to ImportPath (identity entries omitted) +// Deps []string // all (recursively) imported dependencies +// TestImports []string // imports from TestGoFiles +// XTestImports []string // imports from XTestGoFiles // // // Error information // Incomplete bool // this package or a dependency has an error @@ -650,7 +685,7 @@ // path to the vendor directory (for example, "d/vendor/p" instead of "p"), // so that the ImportPath uniquely identifies a given copy of a package. // The Imports, Deps, TestImports, and XTestImports lists also contain these -// expanded imports paths. See golang.org/s/go15vendor for more about vendoring. +// expanded import paths. See golang.org/s/go15vendor for more about vendoring. // // The error information, if any, is // @@ -660,22 +695,25 @@ // Err string // the error itself // } // +// The module information is a Module struct, defined in the discussion +// of list -m below. +// // The template function "join" calls strings.Join. // // The template function "context" returns the build context, defined as: // -// type Context struct { -// GOARCH string // target architecture -// GOOS string // target operating system -// GOROOT string // Go root -// GOPATH string // Go path -// CgoEnabled bool // whether cgo can be used -// 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 -// ReleaseTags []string // releases the current release is compatible with -// InstallSuffix string // suffix to use in the name of the install dir -// } +// type Context struct { +// GOARCH string // target architecture +// GOOS string // target operating system +// GOROOT string // Go root +// GOPATH string // Go path +// CgoEnabled bool // whether cgo can be used +// 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 +// ReleaseTags []string // releases the current release is compatible with +// InstallSuffix string // suffix to use in the name of the install dir +// } // // For more information about the meaning of these fields see the documentation // for the go/build package's Context type. @@ -683,6 +721,18 @@ // The -json flag causes the package data to be printed in JSON format // instead of using the template format. // +// The -compiled flag causes list to set CompiledGoFiles to the Go source +// files presented to the compiler. Typically this means that it repeats +// the files listed in GoFiles and then also adds the Go code generated +// by processing CgoFiles and SwigFiles. The Imports list contains the +// union of all imports from both GoFiles and CompiledGoFiles. +// +// The -deps flag causes list to iterate over not just the named packages +// but also all their dependencies. It visits them in a depth-first post-order +// traversal, so that a package is listed only after all its dependencies. +// Packages not explicitly listed on the command line will have the DepOnly +// field set to true. +// // The -e flag changes the handling of erroneous packages, those that // cannot be found or are malformed. By default, the list command // prints an error to standard error for each erroneous package and @@ -693,19 +743,380 @@ // a non-nil Error field; other information may or may not be missing // (zeroed). // +// The -export flag causes list to set the Export field to the name of a +// file containing up-to-date export information for the given package. +// +// The -find flag causes list to identify the named packages but not +// resolve their dependencies: the Imports and Deps lists will be empty. +// +// The -test flag causes list to report not only the named packages +// but also their test binaries (for packages with tests), to convey to +// source code analysis tools exactly how test binaries are constructed. +// The reported import path for a test binary is the import path of +// the package followed by a ".test" suffix, as in "math/rand.test". +// When building a test, it is sometimes necessary to rebuild certain +// dependencies specially for that test (most commonly the tested +// package itself). The reported import path of a package recompiled +// for a particular test binary is followed by a space and the name of +// the test binary in brackets, as in "math/rand [math/rand.test]" +// or "regexp [sort.test]". The ForTest field is also set to the name +// of the package being tested ("math/rand" or "sort" in the previous +// examples). +// +// The Dir, Target, Shlib, Root, ConflictDir, and Export file paths +// are all absolute paths. +// +// By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir +// (that is, paths relative to Dir, not absolute paths). +// The generated files added when using the -compiled and -test flags +// are absolute paths referring to cached copies of generated Go source files. +// Although they are Go source files, the paths may not end in ".go". +// +// The -m flag causes list to list modules instead of packages. +// +// When listing modules, the -f flag still specifies a format template +// applied to a Go struct, but now a Module struct: +// +// type Module struct { +// Path string // module path +// Version string // module version +// Versions []string // available module versions (with -versions) +// Replace *Module // replaced by this module +// Time *time.Time // time version was created +// Update *Module // available update, if any (with -u) +// Main bool // is this the main module? +// Indirect bool // is this module only an indirect dependency of main module? +// Dir string // directory holding files for this module, if any +// GoMod string // path to go.mod file for this module, if any +// Error *ModuleError // error loading module +// } +// +// type ModuleError struct { +// Err string // the error itself +// } +// +// The default output is to print the module path and then +// information about the version and replacement if any. +// For example, 'go list -m all' might print: +// +// my/main/module +// golang.org/x/text v0.3.0 => /tmp/text +// rsc.io/pdf v0.1.1 +// +// The Module struct has a String method that formats this +// line of output, so that the default format is equivalent +// to -f '{{.String}}'. +// +// Note that when a module has been replaced, its Replace field +// describes the replacement module, and its Dir field is set to +// the replacement's source code, if present. (That is, if Replace +// is non-nil, then Dir is set to Replace.Dir, with no access to +// the replaced source code.) +// +// The -u flag adds information about available upgrades. +// When the latest version of a given module is newer than +// the current one, list -u sets the Module's Update field +// to information about the newer module. +// The Module's String method indicates an available upgrade by +// formatting the newer version in brackets after the current version. +// For example, 'go list -m -u all' might print: +// +// my/main/module +// golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text +// rsc.io/pdf v0.1.1 [v0.1.2] +// +// (For tools, 'go list -m -u -json all' may be more convenient to parse.) +// +// The -versions flag causes list to set the Module's Versions field +// to a list of all known versions of that module, ordered according +// to semantic versioning, earliest to latest. The flag also changes +// the default output format to display the module path followed by the +// space-separated version list. +// +// The arguments to list -m are interpreted as a list of modules, not packages. +// The main module is the module containing the current directory. +// The active modules are the main module and its dependencies. +// With no arguments, list -m shows the main module. +// With arguments, list -m shows the modules specified by the arguments. +// Any of the active modules can be specified by its module path. +// The special pattern "all" specifies all the active modules, first the main +// module and then dependencies sorted by module path. +// A pattern containing "..." specifies the active modules whose +// module paths match the pattern. +// A query of the form path@version specifies the result of that query, +// which is not limited to active modules. +// See 'go help modules' for more about module queries. +// +// The template function "module" takes a single string argument +// that must be a module path or query and returns the specified +// module as a Module struct. If an error occurs, the result will +// be a Module struct with a non-nil Error field. +// // For more about build flags, see 'go help build'. // // For more about specifying packages, see 'go help packages'. // +// For more about modules, see 'go help modules'. +// +// +// Module maintenance +// +// Go mod provides access to operations on modules. +// +// Note that support for modules is built into all the go commands, +// not just 'go mod'. For example, day-to-day adding, removing, upgrading, +// and downgrading of dependencies should be done using 'go get'. +// See 'go help modules' for an overview of module functionality. +// +// Usage: +// +// go mod [arguments] +// +// The commands are: +// +// download download modules to local cache +// edit edit go.mod from tools or scripts +// graph print module requirement graph +// init initialize new module in current directory +// tidy add missing and remove unused modules +// vendor make vendored copy of dependencies +// verify verify dependencies have expected content +// why explain why packages or modules are needed +// +// Use "go help mod " for more information about a command. +// +// Download modules to local cache +// +// Usage: +// +// go mod download [-dir] [-json] [modules] +// +// Download downloads the named modules, which can be module patterns selecting +// dependencies of the main module or module queries of the form path@version. +// With no arguments, download applies to all dependencies of the main module. +// +// The go command will automatically download modules as needed during ordinary +// execution. The "go mod download" command is useful mainly for pre-filling +// the local cache or to compute the answers for a Go module proxy. +// +// By default, download reports errors to standard error but is otherwise silent. +// The -json flag causes download to print a sequence of JSON objects +// to standard output, describing each downloaded module (or failure), +// corresponding to this Go struct: +// +// type Module struct { +// Path string // module path +// Version string // module version +// Error string // error loading module +// Info string // absolute path to cached .info file +// GoMod string // absolute path to cached .mod file +// Zip string // absolute path to cached .zip file +// Dir string // absolute path to cached source root directory +// Sum string // checksum for path, version (as in go.sum) +// GoModSum string // checksum for go.mod (as in go.sum) +// } +// +// See 'go help modules' for more about module queries. +// +// +// Edit go.mod from tools or scripts +// +// Usage: +// +// go mod edit [editing flags] [go.mod] +// +// Edit provides a command-line interface for editing go.mod, +// for use primarily by tools or scripts. It reads only go.mod; +// it does not look up information about the modules involved. +// By default, edit reads and writes the go.mod file of the main module, +// but a different target file can be specified after the editing flags. +// +// The editing flags specify a sequence of editing operations. +// +// The -fmt flag reformats the go.mod file without making other changes. +// This reformatting is also implied by any other modifications that use or +// rewrite the go.mod file. The only time this flag is needed is if no other +// flags are specified, as in 'go mod edit -fmt'. +// +// The -module flag changes the module's path (the go.mod file's module line). +// +// The -require=path@version and -droprequire=path flags +// add and drop a requirement on the given module path and version. +// Note that -require overrides any existing requirements on path. +// These flags are mainly for tools that understand the module graph. +// Users should prefer 'go get path@version' or 'go get path@none', +// which make other go.mod adjustments as needed to satisfy +// constraints imposed by other modules. +// +// The -exclude=path@version and -dropexclude=path@version flags +// add and drop an exclusion for the given module path and version. +// Note that -exclude=path@version is a no-op if that exclusion already exists. +// +// The -replace=old[@v]=new[@v] and -dropreplace=old[@v] flags +// add and drop a replacement of the given module path and version pair. +// If the @v in old@v is omitted, the replacement applies to all versions +// with the old module path. If the @v in new@v is omitted, the new path +// should be a local module root directory, not a module path. +// Note that -replace overrides any existing replacements for old[@v]. +// +// The -require, -droprequire, -exclude, -dropexclude, -replace, +// and -dropreplace editing flags may be repeated, and the changes +// are applied in the order given. +// +// The -print flag prints the final go.mod in its text format instead of +// writing it back to go.mod. +// +// 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 +// Version string +// } +// +// type GoMod struct { +// Module Module +// Require []Require +// Exclude []Module +// Replace []Replace +// } +// +// type Require struct { +// Path string +// Version string +// Indirect bool +// } +// +// type Replace struct { +// Old Module +// New Module +// } +// +// Note that this only describes the go.mod file itself, not other modules +// referred to indirectly. For the full set of modules available to a build, +// use 'go list -m -json all'. +// +// For example, a tool can obtain the go.mod as a data structure by +// parsing the output of 'go mod edit -json' and can then make changes +// by invoking 'go mod edit' with -require, -exclude, and so on. +// +// +// Print module requirement graph +// +// Usage: +// +// go mod graph +// +// 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. +// +// +// Initialize new module in current directory +// +// Usage: +// +// go mod init [module] +// +// Init initializes and writes a new go.mod to the current directory, +// in effect creating a new module rooted at the current directory. +// The file go.mod must not already exist. +// If possible, init will guess the module path from import comments +// (see 'go help importpath') or from version control configuration. +// To override this guess, supply the module path as an argument. +// +// +// Add missing and remove unused modules +// +// Usage: +// +// go mod tidy [-v] +// +// Tidy makes sure go.mod matches the source code in the module. +// It adds any missing modules necessary to build the current module's +// packages and dependencies, and it removes unused modules that +// don't provide any relevant packages. It also adds any missing entries +// to go.sum and removes any unnecessary ones. +// +// The -v flag causes tidy to print information about removed modules +// to standard error. +// +// +// Make vendored copy of dependencies +// +// Usage: +// +// go mod vendor [-v] +// +// Vendor resets the main module's vendor directory to include all packages +// needed to build and test all the main module's packages. +// It does not include test code for vendored packages. +// +// The -v flag causes vendor to print the names of vendored +// modules and packages to standard error. +// +// +// Verify dependencies have expected content +// +// Usage: +// +// go mod verify +// +// Verify checks that the dependencies of the current module, +// which are stored in a local downloaded source cache, have not been +// modified since being downloaded. If all the modules are unmodified, +// verify prints "all modules verified." Otherwise it reports which +// modules have been changed and causes 'go mod' to exit with a +// non-zero status. +// +// +// Explain why packages or modules are needed +// +// Usage: +// +// go mod why [-m] [-vendor] packages... +// +// Why shows a shortest path in the import graph from the main module to +// each of the listed packages. If the -m flag is given, why treats the +// arguments as a list of modules and finds a path to any package in each +// of the modules. +// +// By default, why queries the graph of packages matched by "go list all", +// which includes tests for reachable packages. The -vendor flag causes why +// to exclude tests of dependencies. +// +// The output is a sequence of stanzas, one for each package or module +// name on the command line, separated by blank lines. Each stanza begins +// with a comment line "# package" or "# module" giving the target +// package or module. Subsequent lines give a path through the import +// graph, one package per line. If the package or module is not +// referenced from the main module, the stanza will display a single +// parenthesized note indicating that fact. +// +// For example: +// +// $ go mod why golang.org/x/text/language golang.org/x/text/encoding +// # golang.org/x/text/language +// rsc.io/quote +// rsc.io/sampler +// golang.org/x/text/language +// +// # golang.org/x/text/encoding +// (main module does not need package golang.org/x/text/encoding) +// $ +// // // Compile and run Go program // // Usage: // -// go run [build flags] [-exec xprog] gofiles... [arguments...] +// go run [build flags] [-exec xprog] package [arguments...] // -// Run compiles and runs the main package comprising the named Go source files. -// A Go source file is defined to be a file ending in a literal ".go" suffix. +// Run compiles and runs the named main Go package. +// Typically the package is specified as a list of .go source files, +// 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'. // // 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: @@ -717,7 +1128,10 @@ // cross-compiled programs when a simulator or other execution method is // available. // +// The exit status of Run is not the exit status of the compiled binary. +// // For more about build flags, see 'go help build'. +// For more about specifying packages, see 'go help packages'. // // See also: go build. // @@ -753,9 +1167,12 @@ // // As part of building a test binary, go test runs go vet on the package // and its test source files to identify significant problems. If go vet -// finds any problems, go test reports those and does not run the test binary. -// Only a high-confidence subset of the default go vet checks are used. -// To disable the running of go vet, use the -vet=off flag. +// finds any problems, go test reports those and does not run the test +// binary. Only a high-confidence subset of the default go vet checks are +// used. That subset is: 'atomic', 'bool', 'buildtags', 'nilfunc', and +// 'printf'. You can see the documentation for these and other vet tests +// via "go doc cmd/vet". To disable the running of go vet, use the +// -vet=off flag. // // All test output and summary lines are printed to the go command's // standard output, even if the test printed them to its own standard @@ -887,25 +1304,6 @@ // See also: go fmt, go fix. // // -// Calling between Go and C -// -// There are two different ways to call between Go and C/C++ code. -// -// The first is the cgo tool, which is part of the Go distribution. For -// information on how to use it see the cgo documentation (go doc cmd/cgo). -// -// The second is the SWIG program, which is a general tool for -// interfacing between languages. For information on SWIG see -// http://swig.org/. When running go build, any file with a .swig -// extension will be passed to SWIG. Any file with a .swigcxx extension -// will be passed to SWIG with the -c++ option. -// -// When either cgo or SWIG is used, go build will pass any .c, .m, .s, -// or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++ -// compiler. The CC or CXX environment variables may be set to determine -// the C or C++ compiler, respectively, to use. -// -// // Build modes // // The 'go build' and 'go install' commands take a -buildmode argument which @@ -952,6 +1350,25 @@ // import, into a Go plugin. Packages not named main are ignored. // // +// Calling between Go and C +// +// There are two different ways to call between Go and C/C++ code. +// +// The first is the cgo tool, which is part of the Go distribution. For +// information on how to use it see the cgo documentation (go doc cmd/cgo). +// +// The second is the SWIG program, which is a general tool for +// interfacing between languages. For information on SWIG see +// http://swig.org/. When running go build, any file with a .swig +// extension will be passed to SWIG. Any file with a .swigcxx extension +// will be passed to SWIG with the -c++ option. +// +// When either cgo or SWIG is used, go build will pass any .c, .m, .s, +// or .S files to the C compiler, and any .cc, .cpp, .cxx files to the C++ +// compiler. The CC or CXX environment variables may be set to determine +// the C or C++ compiler, respectively, to use. +// +// // Build and test caching // // The go command caches build outputs for reuse in future builds. @@ -959,6 +1376,7 @@ // in the standard user cache directory for the current operating system. // Setting the GOCACHE environment variable overrides this default, // and running 'go env GOCACHE' prints the current cache directory. +// You can set the variable to 'off' to disable the cache. // // The go command periodically deletes cached data that has not been // used recently. Running 'go clean -cache' deletes all cached data. @@ -991,6 +1409,129 @@ // decisions about whether to reuse a cached test result. // // +// Environment variables +// +// The go command, and the tools it invokes, examine a few different +// environment variables. For many of these, you can see the default +// value of on your system by running 'go env NAME', where NAME is the +// name of the variable. +// +// General-purpose environment variables: +// +// GCCGO +// The gccgo command to run for 'go build -compiler=gccgo'. +// GOARCH +// The architecture, or processor, for which to compile code. +// Examples are amd64, 386, arm, ppc64. +// GOBIN +// The directory where 'go install' will install a command. +// GOCACHE +// The directory where the go command will store cached +// information for reuse in future builds. +// GOFLAGS +// A space-separated list of -flag=value settings to apply +// to go commands by default, when the given flag is known by +// the current command. Flags listed on the command-line +// are applied after this list and therefore override it. +// GOOS +// The operating system for which to compile code. +// Examples are linux, darwin, windows, netbsd. +// GOPATH +// For more details see: 'go help gopath'. +// GOPROXY +// URL of Go module proxy. See 'go help goproxy'. +// GORACE +// Options for the race detector. +// See https://golang.org/doc/articles/race_detector.html. +// GOROOT +// The root of the go tree. +// GOTMPDIR +// The directory where the go command will write +// temporary source files, packages, and binaries. +// +// Environment variables for use with cgo: +// +// CC +// The command to use to compile C code. +// CGO_ENABLED +// Whether the cgo command is supported. Either 0 or 1. +// CGO_CFLAGS +// Flags that cgo will pass to the compiler when compiling +// C code. +// CGO_CFLAGS_ALLOW +// A regular expression specifying additional flags to allow +// to appear in #cgo CFLAGS source code directives. +// Does not apply to the CGO_CFLAGS environment variable. +// CGO_CFLAGS_DISALLOW +// A regular expression specifying flags that must be disallowed +// from appearing in #cgo CFLAGS source code directives. +// Does not apply to the CGO_CFLAGS environment variable. +// CGO_CPPFLAGS, CGO_CPPFLAGS_ALLOW, CGO_CPPFLAGS_DISALLOW +// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, +// but for the C preprocessor. +// CGO_CXXFLAGS, CGO_CXXFLAGS_ALLOW, CGO_CXXFLAGS_DISALLOW +// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, +// but for the C++ compiler. +// CGO_FFLAGS, CGO_FFLAGS_ALLOW, CGO_FFLAGS_DISALLOW +// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, +// but for the Fortran compiler. +// CGO_LDFLAGS, CGO_LDFLAGS_ALLOW, CGO_LDFLAGS_DISALLOW +// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, +// but for the linker. +// CXX +// The command to use to compile C++ code. +// PKG_CONFIG +// Path to pkg-config tool. +// +// Architecture-specific environment variables: +// +// GOARM +// For GOARCH=arm, the ARM architecture for which to compile. +// Valid values are 5, 6, 7. +// GO386 +// For GOARCH=386, the floating point instruction set. +// Valid values are 387, sse2. +// GOMIPS +// For GOARCH=mips{,le}, whether to use floating point instructions. +// Valid values are hardfloat (default), softfloat. +// GOMIPS64 +// For GOARCH=mips64{,le}, whether to use floating point instructions. +// Valid values are hardfloat (default), softfloat. +// +// Special-purpose environment variables: +// +// GCCGOTOOLDIR +// If set, where to find gccgo tools, such as cgo. +// The default is based on how gccgo was configured. +// GOROOT_FINAL +// The root of the installed Go tree, when it is +// installed in a location other than where it is built. +// File names in stack traces are rewritten from GOROOT to +// GOROOT_FINAL. +// GO_EXTLINK_ENABLED +// Whether the linker should use external linking mode +// when using -linkmode=auto with code that uses cgo. +// Set to 0 to disable external linking mode, 1 to enable it. +// GIT_ALLOW_PROTOCOL +// Defined by Git. A colon-separated list of schemes that are allowed to be used +// with git fetch/clone. If set, any scheme not explicitly mentioned will be +// considered insecure by 'go get'. +// +// Additional information available from 'go env' but not read from the environment: +// +// GOEXE +// The executable file name suffix (".exe" on Windows, "" on other systems). +// GOHOSTARCH +// The architecture (GOARCH) of the Go toolchain binaries. +// GOHOSTOS +// The operating system (GOOS) of the Go toolchain binaries. +// GOMOD +// The absolute path to the go.mod of the main module, +// or the empty string if not using modules. +// GOTOOLDIR +// The directory where the go tools (compile, cover, doc, etc...) are installed. +// +// // File types // // The go command examines the contents of a restricted set of files @@ -1036,6 +1577,85 @@ // command. // // +// The go.mod file +// +// A module version is defined by a tree of source files, with a go.mod +// file in its root. When the go command is run, it looks in the current +// directory and then successive parent directories to find the go.mod +// marking the root of the main (current) module. +// +// The go.mod file itself is line-oriented, with // comments but +// no /* */ comments. Each line holds a single directive, made up of a +// verb followed by arguments. For example: +// +// module my/thing +// require other/thing v1.0.2 +// require new/thing v2.3.4 +// exclude old/thing v1.2.3 +// replace bad/thing v1.4.5 => good/thing v1.4.5 +// +// The verbs are module, to define the module path; require, to require +// a particular module at a given version or later; exclude, to exclude +// a particular module version from use; and replace, to replace a module +// version with a different module version. Exclude and replace apply only +// in the main module's go.mod and are ignored in dependencies. +// See https://research.swtch.com/vgo-mvs for details. +// +// The leading verb can be factored out of adjacent lines to create a block, +// like in Go imports: +// +// require ( +// new/thing v2.3.4 +// old/thing v1.2.3 +// ) +// +// The go.mod file is designed both to be edited directly and to be +// easily updated by tools. The 'go mod edit' command can be used to +// parse and edit the go.mod file from programs and tools. +// See 'go help mod edit'. +// +// The go command automatically updates go.mod each time it uses the +// module graph, to make sure go.mod always accurately reflects reality +// and is properly formatted. For example, consider this go.mod file: +// +// module M +// +// require ( +// A v1 +// B v1.0.0 +// C v1.0.0 +// D v1.2.3 +// E dev +// ) +// +// exclude D v1.2.3 +// +// The update rewrites non-canonical version identifiers to semver form, +// so A's v1 becomes v1.0.0 and E's dev becomes the pseudo-version for the +// latest commit on the dev branch, perhaps v0.0.0-20180523231146-b3f5c0f6e5f1. +// +// The update modifies requirements to respect exclusions, so the +// requirement on the excluded D v1.2.3 is updated to use the next +// available version of D, perhaps D v1.2.4 or D v1.3.0. +// +// The update removes redundant or misleading requirements. +// For example, if A v1.0.0 itself requires B v1.2.0 and C v1.0.0, +// then go.mod's requirement of B v1.0.0 is misleading (superseded by +// A's need for v1.2.0), and its requirement of C v1.0.0 is redundant +// (implied by A's need for the same version), so both will be removed. +// If module M contains packages that directly import packages from B or +// C, then the requirements will be kept but updated to the actual +// versions being used. +// +// Finally, the update reformats the go.mod in a canonical formatting, so +// that future mechanical changes will result in minimal diffs. +// +// Because the module graph defines the meaning of import statements, any +// commands that load packages also use and therefore update go.mod, +// including go build, go get, go install, go list, go test, go mod graph, +// go mod tidy, and go mod why. +// +// // GOPATH environment variable // // The Go path is used to resolve import statements. @@ -1102,6 +1722,12 @@ // // See https://golang.org/doc/code.html for an example. // +// GOPATH and Modules +// +// When using modules, GOPATH is no longer used for resolving imports. +// However, it is still used to store downloaded source code (in GOPATH/pkg/mod) +// and compiled commands (in GOPATH/bin). +// // Internal Directories // // Code in or below a directory named "internal" is importable only @@ -1185,103 +1811,67 @@ // See https://golang.org/s/go15vendor for details. // // -// Environment variables +// Module proxy protocol // -// The go command, and the tools it invokes, examine a few different -// environment variables. For many of these, you can see the default -// value of on your system by running 'go env NAME', where NAME is the -// name of the variable. +// The go command by default downloads modules from version control systems +// directly, just as 'go get' always has. The GOPROXY environment variable allows +// further control over the download source. If GOPROXY is unset, is the empty string, +// or is the string "direct", downloads use the default direct connection to version +// control systems. Setting GOPROXY to "off" disallows downloading modules from +// any source. Otherwise, GOPROXY is expected to be the URL of a module proxy, +// in which case the go command will fetch all modules from that proxy. +// No matter the source of the modules, downloaded modules must match existing +// entries in go.sum (see 'go help modules' for discussion of verification). // -// General-purpose environment variables: +// A Go module proxy is any web server that can respond to GET requests for +// URLs of a specified form. The requests have no query parameters, so even +// a site serving from a fixed file system (including a file:/// URL) +// can be a module proxy. // -// GCCGO -// The gccgo command to run for 'go build -compiler=gccgo'. -// GOARCH -// The architecture, or processor, for which to compile code. -// Examples are amd64, 386, arm, ppc64. -// GOBIN -// The directory where 'go install' will install a command. -// GOOS -// The operating system for which to compile code. -// Examples are linux, darwin, windows, netbsd. -// GOPATH -// For more details see: 'go help gopath'. -// GORACE -// Options for the race detector. -// See https://golang.org/doc/articles/race_detector.html. -// GOROOT -// The root of the go tree. -// GOTMPDIR -// The directory where the go command will write -// temporary source files, packages, and binaries. -// GOCACHE -// The directory where the go command will store -// cached information for reuse in future builds. +// The GET requests sent to a Go module proxy are: // -// Environment variables for use with cgo: +// GET $GOPROXY//@v/list returns a list of all known versions of the +// given module, one per line. // -// CC -// The command to use to compile C code. -// CGO_ENABLED -// Whether the cgo command is supported. Either 0 or 1. -// CGO_CFLAGS -// Flags that cgo will pass to the compiler when compiling -// C code. -// CGO_CFLAGS_ALLOW -// A regular expression specifying additional flags to allow -// to appear in #cgo CFLAGS source code directives. -// Does not apply to the CGO_CFLAGS environment variable. -// CGO_CFLAGS_DISALLOW -// A regular expression specifying flags that must be disallowed -// from appearing in #cgo CFLAGS source code directives. -// Does not apply to the CGO_CFLAGS environment variable. -// CGO_CPPFLAGS, CGO_CPPFLAGS_ALLOW, CGO_CPPFLAGS_DISALLOW -// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, -// but for the C preprocessor. -// CGO_CXXFLAGS, CGO_CXXFLAGS_ALLOW, CGO_CXXFLAGS_DISALLOW -// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, -// but for the C++ compiler. -// CGO_FFLAGS, CGO_FFLAGS_ALLOW, CGO_FFLAGS_DISALLOW -// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, -// but for the Fortran compiler. -// CGO_LDFLAGS, CGO_LDFLAGS_ALLOW, CGO_LDFLAGS_DISALLOW -// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW, -// but for the linker. -// CXX -// The command to use to compile C++ code. -// PKG_CONFIG -// Path to pkg-config tool. +// GET $GOPROXY//@v/.info returns JSON-formatted metadata +// about that version of the given module. // -// Architecture-specific environment variables: +// GET $GOPROXY//@v/.mod returns the go.mod file +// for that version of the given module. // -// GOARM -// For GOARCH=arm, the ARM architecture for which to compile. -// Valid values are 5, 6, 7. -// GO386 -// For GOARCH=386, the floating point instruction set. -// Valid values are 387, sse2. -// GOMIPS -// For GOARCH=mips{,le}, whether to use floating point instructions. -// Valid values are hardfloat (default), softfloat. +// GET $GOPROXY//@v/.zip returns the zip archive +// for that version of the given module. // -// Special-purpose environment variables: +// To avoid problems when serving from case-sensitive file systems, +// the and elements are case-encoded, replacing every +// uppercase letter with an exclamation mark followed by the corresponding +// lower-case letter: github.com/Azure encodes as github.com/!azure. // -// GCCGOTOOLDIR -// If set, where to find gccgo tools, such as cgo. -// The default is based on how gccgo was configured. -// GOROOT_FINAL -// The root of the installed Go tree, when it is -// installed in a location other than where it is built. -// File names in stack traces are rewritten from GOROOT to -// GOROOT_FINAL. -// GO_EXTLINK_ENABLED -// Whether the linker should use external linking mode -// when using -linkmode=auto with code that uses cgo. -// Set to 0 to disable external linking mode, 1 to enable it. -// GIT_ALLOW_PROTOCOL -// Defined by Git. A colon-separated list of schemes that are allowed to be used -// with git fetch/clone. If set, any scheme not explicitly mentioned will be -// considered insecure by 'go get'. +// The JSON-formatted metadata about a given module corresponds to +// this Go data structure, which may be expanded in the future: +// +// type Info struct { +// Version string // version string +// Time time.Time // commit time +// } +// +// The zip archive for a specific version of a given module is a +// standard zip file that contains the file tree corresponding +// to the module's source code and related files. The archive uses +// slash-separated paths, and every file path in the archive must +// begin with @/, where the module and version are +// substituted directly, not case-encoded. The root of the module +// file tree corresponds to the @/ prefix in the +// archive. +// +// Even when downloading directly from version control systems, +// the go command synthesizes explicit info, mod, and zip files +// and stores them in its local cache, $GOPATH/pkg/mod/cache/download, +// the same as if it had downloaded them directly from a proxy. +// The cache layout is the same as the proxy URL space, so +// serving $GOPATH/pkg/mod/cache/download at (or copying it to) +// https://example.com/proxy would let other users access those +// cached module versions with GOPROXY=https://example.com/proxy. // // // Import path syntax @@ -1361,6 +1951,7 @@ // that repository. The supported version control systems are: // // Bazaar .bzr +// Fossil .fossil // Git .git // Mercurial .hg // Subversion .svn @@ -1404,7 +1995,7 @@ // In particular, it should appear before any raw JavaScript or CSS, // to avoid confusing the go command's restricted parser. // -// The vcs is one of "git", "hg", "svn", etc, +// The vcs is one of "bzr", "fossil", "git", "hg", "svn". // // The repo-root is the root of the version control system // containing a scheme and not containing a .vcs qualifier. @@ -1426,12 +2017,22 @@ // same meta tag and then git clone https://code.org/r/p/exproj into // GOPATH/src/example.org. // -// New downloaded packages are written to the first directory listed in the GOPATH -// environment variable (For more details see: 'go help gopath'). +// When using GOPATH, downloaded packages are written to the first directory +// listed in the GOPATH environment variable. +// (See 'go help gopath-get' and 'go help gopath'.) // -// The go command attempts to download the version of the -// package appropriate for the Go release being used. -// Run 'go help get' for more. +// When using modules, downloaded packages are stored in the module cache. +// (See 'go help modules-get' and 'go help goproxy'.) +// +// When using modules, an additional variant of the go-import meta tag is +// recognized and is preferred over those listing version control systems. +// That variant uses "mod" as the vcs in the content value, as in: +// +// +// +// This tag means to fetch modules with paths beginning with example.org +// from the module proxy available at the URL https://code.org/moduleproxy. +// See 'go help goproxy' for details about the proxy protocol. // // Import path checking // @@ -1454,10 +2055,484 @@ // This makes it possible to copy code into alternate locations in vendor trees // without needing to update import comments. // +// Import path checking is also disabled when using modules. +// Import path comments are obsoleted by the go.mod file's module statement. +// // See https://golang.org/s/go14customimport for details. // // -// Package lists +// Modules, module versions, and more +// +// A module is a collection of related Go packages. +// Modules are the unit of source code interchange and versioning. +// The go command has direct support for working with modules, +// including recording and resolving dependencies on other modules. +// Modules replace the old GOPATH-based approach to specifying +// which source files are used in a given build. +// +// Preliminary module support +// +// Go 1.11 includes preliminary support for Go modules, +// including a new module-aware 'go get' command. +// We intend to keep revising this support, while preserving compatibility, +// until it can be declared official (no longer preliminary), +// and then at a later point we may remove support for work +// in GOPATH and the old 'go get' command. +// +// The quickest way to take advantage of the new Go 1.11 module support +// is to check out your repository into a directory outside GOPATH/src, +// create a go.mod file (described in the next section) there, and run +// go commands from within that file tree. +// +// For more fine-grained control, the module support in Go 1.11 respects +// a temporary environment variable, GO111MODULE, which can be set to one +// of three string values: off, on, or auto (the default). +// If GO111MODULE=off, then the go command never uses the +// new module support. Instead it looks in vendor directories and GOPATH +// to find dependencies; we now refer to this as "GOPATH mode." +// If GO111MODULE=on, then the go command requires the use of modules, +// never consulting GOPATH. We refer to this as the command being +// module-aware or running in "module-aware mode". +// If GO111MODULE=auto or is unset, then the go command enables or +// disables module support based on the current directory. +// Module support is enabled only when the current directory is outside +// GOPATH/src and itself contains a go.mod file or is below a directory +// containing a go.mod file. +// +// In module-aware mode, GOPATH no longer defines the meaning of imports +// during a build, but it still stores downloaded dependencies (in GOPATH/pkg/mod) +// and installed commands (in GOPATH/bin, unless GOBIN is set). +// +// Defining a module +// +// A module is defined by a tree of Go source files with a go.mod file +// in the tree's root directory. The directory containing the go.mod file +// is called the module root. Typically the module root will also correspond +// to a source code repository root (but in general it need not). +// The module is the set of all Go packages in the module root and its +// subdirectories, but excluding subtrees with their own go.mod files. +// +// The "module path" is the import path prefix corresponding to the module root. +// The go.mod file defines the module path and lists the specific versions +// of other modules that should be used when resolving imports during a build, +// by giving their module paths and versions. +// +// For example, this go.mod declares that the directory containing it is the root +// of the module with path example.com/m, and it also declares that the module +// depends on specific versions of golang.org/x/text and gopkg.in/yaml.v2: +// +// module example.com/m +// +// require ( +// golang.org/x/text v0.3.0 +// gopkg.in/yaml.v2 v2.1.0 +// ) +// +// The go.mod file can also specify replacements and excluded versions +// that only apply when building the module directly; they are ignored +// when the module is incorporated into a larger build. +// For more about the go.mod file, see 'go help go.mod'. +// +// To start a new module, simply create a go.mod file in the root of the +// module's directory tree, containing only a module statement. +// The 'go mod init' command can be used to do this: +// +// go mod init example.com/m +// +// In a project already using an existing dependency management tool like +// godep, glide, or dep, 'go mod init' will also add require statements +// matching the existing configuration. +// +// Once the go.mod file exists, no additional steps are required: +// go commands like 'go build', 'go test', or even 'go list' will automatically +// add new dependencies as needed to satisfy imports. +// +// The main module and the build list +// +// The "main module" is the module containing the directory where the go command +// is run. The go command finds the module root by looking for a go.mod in the +// current directory, or else the current directory's parent directory, +// or else the parent's parent directory, and so on. +// +// The main module's go.mod file defines the precise set of packages available +// for use by the go command, through require, replace, and exclude statements. +// Dependency modules, found by following require statements, also contribute +// to the definition of that set of packages, but only through their go.mod +// files' require statements: any replace and exclude statements in dependency +// modules are ignored. The replace and exclude statements therefore allow the +// main module complete control over its own build, without also being subject +// to complete control by dependencies. +// +// The set of modules providing packages to builds is called the "build list". +// The build list initially contains only the main module. Then the go command +// adds to the list the exact module versions required by modules already +// on the list, recursively, until there is nothing left to add to the list. +// If multiple versions of a particular module are added to the list, +// then at the end only the latest version (according to semantic version +// ordering) is kept for use in the build. +// +// The 'go list' command provides information about the main module +// and the build list. For example: +// +// go list -m # print path of main module +// go list -m -f={{.Dir}} # print root directory of main module +// go list -m all # print build list +// +// Maintaining module requirements +// +// The go.mod file is meant to be readable and editable by both +// programmers and tools. The go command itself automatically updates the go.mod file +// to maintain a standard formatting and the accuracy of require statements. +// +// Any go command that finds an unfamiliar import will look up the module +// containing that import and add the latest version of that module +// to go.mod automatically. In most cases, therefore, it suffices to +// add an import to source code and run 'go build', 'go test', or even 'go list': +// as part of analyzing the package, the go command will discover +// and resolve the import and update the go.mod file. +// +// Any go command can determine that a module requirement is +// missing and must be added, even when considering only a single +// package from the module. On the other hand, determining that a module requirement +// is no longer necessary and can be deleted requires a full view of +// all packages in the module, across all possible build configurations +// (architectures, operating systems, build tags, and so on). +// The 'go mod tidy' command builds that view and then +// adds any missing module requirements and removes unnecessary ones. +// +// As part of maintaining the require statements in go.mod, the go command +// tracks which ones provide packages imported directly by the current module +// and which ones provide packages only used indirectly by other module +// dependencies. Requirements needed only for indirect uses are marked with a +// "// indirect" comment in the go.mod file. Indirect requirements are +// automatically removed from the go.mod file once they are implied by other +// direct requirements. Indirect requirements only arise when using modules +// that fail to state some of their own dependencies or when explicitly +// upgrading a module's dependencies ahead of its own stated requirements. +// +// Because of this automatic maintenance, the information in go.mod is an +// up-to-date, readable description of the build. +// +// The 'go get' command updates go.mod to change the module versions used in a +// build. An upgrade of one module may imply upgrading others, and similarly a +// downgrade of one module may imply downgrading others. The 'go get' command +// makes these implied changes as well. If go.mod is edited directly, commands +// like 'go build' or 'go list' will assume that an upgrade is intended and +// automatically make any implied upgrades and update go.mod to reflect them. +// +// The 'go mod' command provides other functionality for use in maintaining +// and understanding modules and go.mod files. See 'go help mod'. +// +// The -mod build flag provides additional control over updating and use of go.mod. +// +// If invoked with -mod=readonly, the go command is disallowed from the implicit +// automatic updating of go.mod described above. Instead, it fails when any changes +// to go.mod are needed. This setting is most useful to check that go.mod does +// not need updates, such as in a continuous integration and testing system. +// The "go get" command remains permitted to update go.mod even with -mod=readonly, +// and the "go mod" commands do not take the -mod flag (or any other build flags). +// +// If invoked with -mod=vendor, the go command assumes that the vendor +// directory holds the correct copies of dependencies and ignores +// the dependency descriptions in go.mod. +// +// Pseudo-versions +// +// The go.mod file and the go command more generally use semantic versions as +// the standard form for describing module versions, so that versions can be +// compared to determine which should be considered earlier or later than another. +// A module version like v1.2.3 is introduced by tagging a revision in the +// underlying source repository. Untagged revisions can be referred to +// using a "pseudo-version" like v0.0.0-yyyymmddhhmmss-abcdefabcdef, +// where the time is the commit time in UTC and the final suffix is the prefix +// of the commit hash. The time portion ensures that two pseudo-versions can +// be compared to determine which happened later, the commit hash identifes +// the underlying commit, and the prefix (v0.0.0- in this example) is derived from +// the most recent tagged version in the commit graph before this commit. +// +// There are three pseudo-version forms: +// +// vX.0.0-yyyymmddhhmmss-abcdefabcdef is used when there is no earlier +// versioned commit with an appropriate major version before the target commit. +// (This was originally the only form, so some older go.mod files use this form +// even for commits that do follow tags.) +// +// vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef is used when the most +// recent versioned commit before the target commit is vX.Y.Z-pre. +// +// vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef is used when the most +// recent versioned commit before the target commit is vX.Y.Z. +// +// Pseudo-versions never need to be typed by hand: the go command will accept +// the plain commit hash and translate it into a pseudo-version (or a tagged +// version if available) automatically. This conversion is an example of a +// module query. +// +// Module queries +// +// The go command accepts a "module query" in place of a module version +// both on the command line and in the main module's go.mod file. +// (After evaluating a query found in the main module's go.mod file, +// the go command updates the file to replace the query with its result.) +// +// A fully-specified semantic version, such as "v1.2.3", +// evaluates to that specific version. +// +// A semantic version prefix, such as "v1" or "v1.2", +// evaluates to the latest available tagged version with that prefix. +// +// A semantic version comparison, such as "=v1.5.6", +// evaluates to the available tagged version nearest to the comparison target +// (the latest version for < and <=, the earliest version for > and >=). +// +// The string "latest" matches the latest available tagged version, +// or else the underlying source repository's latest untagged revision. +// +// A revision identifier for the underlying source repository, +// such as a commit hash prefix, revision tag, or branch name, +// selects that specific code revision. If the revision is +// also tagged with a semantic version, the query evaluates to +// that semantic version. Otherwise the query evaluates to a +// pseudo-version for the commit. +// +// All queries prefer release versions to pre-release versions. +// For example, " 1 { + t.Fatal("go build mentioned import cycle more than once") + } + + // Don't hang forever. + tg.run("list", "-e", "-json", "selfimport") +} + +func TestListImportMap(t *testing.T) { + skipIfGccgo(t, "gccgo does not have standard packages") + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.run("list", "-f", "{{.ImportPath}}: {{.ImportMap}}", "net", "fmt") + tg.grepStdout(`^net: map\[(.* )?golang_org/x/net/dns/dnsmessage:vendor/golang_org/x/net/dns/dnsmessage.*\]`, "net/http should have rewritten dnsmessage import") + tg.grepStdout(`^fmt: map\[\]`, "fmt should have no rewritten imports") + tg.run("list", "-deps", "-test", "-f", "{{.ImportPath}} MAP: {{.ImportMap}}\n{{.ImportPath}} IMPORT: {{.Imports}}", "fmt") + tg.grepStdout(`^flag \[fmt\.test\] MAP: map\[fmt:fmt \[fmt\.test\]\]`, "flag [fmt.test] should import fmt [fmt.test] as fmt") + tg.grepStdout(`^fmt\.test MAP: map\[(.* )?testing:testing \[fmt\.test\]`, "fmt.test should import testing [fmt.test] as testing") + tg.grepStdout(`^fmt\.test MAP: map\[(.* )?testing:testing \[fmt\.test\]`, "fmt.test should import testing [fmt.test] as testing") + tg.grepStdoutNot(`^fmt\.test MAP: map\[(.* )?os:`, "fmt.test should not import a modified os") + tg.grepStdout(`^fmt\.test IMPORT: \[fmt \[fmt\.test\] fmt_test \[fmt\.test\] os testing \[fmt\.test\] testing/internal/testdeps \[fmt\.test\]\]`, "wrong imports for fmt.test") +} + // cmd/go: custom import path checking should not apply to Go packages without import comment. func TestIssue10952(t *testing.T) { testenv.MustHaveExternalNetwork(t) @@ -1459,6 +1292,7 @@ func TestGetGitDefaultBranch(t *testing.T) { tg.grepStdout(`\* another-branch`, "not on correct default branch") } +// Security issue. Don't disable. See golang.org/issue/22125. func TestAccidentalGitCheckout(t *testing.T) { testenv.MustHaveExternalNetwork(t) if _, err := exec.LookPath("git"); err != nil { @@ -1469,13 +1303,17 @@ func TestAccidentalGitCheckout(t *testing.T) { defer tg.cleanup() tg.parallel() tg.tempDir("src") + tg.setenv("GOPATH", tg.path(".")) tg.runFail("get", "-u", "vcs-test.golang.org/go/test1-svn-git") tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason") - tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main") - tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason") + if _, err := os.Stat(tg.path("SrC")); err == nil { + // This case only triggers on a case-insensitive file system. + tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main") + tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason") + } } func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) { @@ -1483,7 +1321,8 @@ func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) { defer tg.cleanup() tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) tg.runFail("test", "syntaxerror") - tg.grepStderr("FAIL", "go test did not say FAIL") + tg.grepStderr("x_test.go:", "did not diagnose error") + tg.grepStdout("FAIL", "go test did not say FAIL") } func TestWildcardsDoNotLookInUselessDirectories(t *testing.T) { @@ -1580,6 +1419,7 @@ func TestRelativeGOBINFail(t *testing.T) { tg := testgo(t) defer tg.cleanup() tg.tempFile("triv.go", `package main; func main() {}`) + tg.cd(tg.path(".")) tg.setenv("GOBIN", ".") tg.runFail("install") tg.grepStderr("cannot install, GOBIN must be an absolute path", "go install must fail if $GOBIN is a relative path") @@ -1634,12 +1474,6 @@ func TestPackageMainTestCompilerFlags(t *testing.T) { tg.grepStderr(`([\\/]compile|gccgo).* (-p p1|-fgo-pkgpath=p1).*p1\.go`, "should have run compile -p p1 p1.go") } -// The runtime version string takes one of two forms: -// "go1.X[.Y]" for Go releases, and "devel +hash" at tip. -// Determine whether we are in a released copy by -// inspecting the version. -var isGoRelease = strings.HasPrefix(runtime.Version(), "go1") - // Issue 12690 func TestPackageNotStaleWithTrailingSlash(t *testing.T) { skipIfGccgo(t, "gccgo does not have GOROOT") @@ -1727,8 +1561,8 @@ func TestGoGetTestOnlyPkg(t *testing.T) { defer tg.cleanup() tg.tempDir("gopath") tg.setenv("GOPATH", tg.path("gopath")) - tg.run("get", "golang.org/x/tour/content") - tg.run("get", "-t", "golang.org/x/tour/content") + tg.run("get", "golang.org/x/tour/content...") + tg.run("get", "-t", "golang.org/x/tour/content...") } func TestInstalls(t *testing.T) { @@ -1854,7 +1688,7 @@ func TestGoListStdDoesNotIncludeCommands(t *testing.T) { } func TestGoListCmdOnlyShowsCommands(t *testing.T) { - skipIfGccgo(t, "gccgo has no GOROOT") + skipIfGccgo(t, "gccgo does not have GOROOT") tooSlow(t) tg := testgo(t) defer tg.cleanup() @@ -1894,6 +1728,118 @@ func TestGoListDeps(t *testing.T) { tg.tempFile("src/p1/p2/p3/p4/p.go", "package p4\n") tg.run("list", "-f", "{{.Deps}}", "p1") tg.grepStdout("p1/p2/p3/p4", "Deps(p1) does not mention p4") + + tg.run("list", "-deps", "p1") + tg.grepStdout("p1/p2/p3/p4", "-deps p1 does not mention p4") + + if runtime.Compiler != "gccgo" { + // Check the list is in dependency order. + tg.run("list", "-deps", "math") + want := "internal/cpu\nunsafe\nmath\n" + out := tg.stdout.String() + if !strings.Contains(out, "internal/cpu") { + // Some systems don't use internal/cpu. + want = "unsafe\nmath\n" + } + if tg.stdout.String() != want { + t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want) + } + } +} + +func TestGoListTest(t *testing.T) { + skipIfGccgo(t, "gccgo does not have standard packages") + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOCACHE", tg.tempdir) + + tg.run("list", "-test", "-deps", "sort") + tg.grepStdout(`^sort.test$`, "missing test main") + tg.grepStdout(`^sort$`, "missing real sort") + tg.grepStdout(`^sort \[sort.test\]$`, "missing test copy of sort") + tg.grepStdout(`^testing \[sort.test\]$`, "missing test copy of testing") + tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing") + + tg.run("list", "-test", "sort") + tg.grepStdout(`^sort.test$`, "missing test main") + tg.grepStdout(`^sort$`, "missing real sort") + tg.grepStdout(`^sort \[sort.test\]$`, "unexpected test copy of sort") + tg.grepStdoutNot(`^testing \[sort.test\]$`, "unexpected test copy of testing") + tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing") + + tg.run("list", "-test", "cmd/dist", "cmd/doc") + tg.grepStdout(`^cmd/dist$`, "missing cmd/dist") + tg.grepStdout(`^cmd/doc$`, "missing cmd/doc") + tg.grepStdout(`^cmd/doc\.test$`, "missing cmd/doc test") + tg.grepStdoutNot(`^cmd/dist\.test$`, "unexpected cmd/dist test") + tg.grepStdoutNot(`^testing`, "unexpected testing") + + tg.run("list", "-test", "runtime/cgo") + tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo") + + tg.run("list", "-deps", "-f", "{{if .DepOnly}}{{.ImportPath}}{{end}}", "sort") + tg.grepStdout(`^reflect$`, "missing reflect") + tg.grepStdoutNot(`^sort`, "unexpected sort") +} + +func TestGoListCompiledCgo(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOCACHE", tg.tempdir) + + tg.run("list", "-f", `{{join .CgoFiles "\n"}}`, "net") + if tg.stdout.String() == "" { + t.Skip("net does not use cgo") + } + if strings.Contains(tg.stdout.String(), tg.tempdir) { + t.Fatalf(".CgoFiles unexpectedly mentioned cache %s", tg.tempdir) + } + tg.run("list", "-compiled", "-f", `{{.Dir}}{{"\n"}}{{join .CompiledGoFiles "\n"}}`, "net") + if !strings.Contains(tg.stdout.String(), tg.tempdir) { + t.Fatalf(".CompiledGoFiles with -compiled did not mention cache %s", tg.tempdir) + } + dir := "" + for _, file := range strings.Split(tg.stdout.String(), "\n") { + if file == "" { + continue + } + if dir == "" { + dir = file + continue + } + if !strings.Contains(file, "/") && !strings.Contains(file, `\`) { + file = filepath.Join(dir, file) + } + if _, err := os.Stat(file); err != nil { + t.Fatalf("cannot find .CompiledGoFiles result %s: %v", file, err) + } + } +} + +func TestGoListExport(t *testing.T) { + skipIfGccgo(t, "gccgo does not have standard packages") + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOCACHE", tg.tempdir) + + tg.run("list", "-f", "{{.Export}}", "strings") + if tg.stdout.String() != "" { + t.Fatalf(".Export without -export unexpectedly set") + } + tg.run("list", "-export", "-f", "{{.Export}}", "strings") + file := strings.TrimSpace(tg.stdout.String()) + if file == "" { + t.Fatalf(".Export with -export was empty") + } + if _, err := os.Stat(file); err != nil { + t.Fatalf("cannot find .Export result %s: %v", file, err) + } } // Issue 4096. Validate the output of unsuccessful go install foo/quxx. @@ -1966,6 +1912,17 @@ func homeEnvName() string { } } +func tempEnvName() string { + switch runtime.GOOS { + case "windows": + return "TMP" + case "plan9": + return "TMPDIR" // actually plan 9 doesn't have one at all but this is fine + default: + return "TMPDIR" + } +} + func TestDefaultGOPATH(t *testing.T) { tg := testgo(t) defer tg.cleanup() @@ -2635,6 +2592,18 @@ func TestCoverageFunc(t *testing.T) { tg.grepStdoutNot(`\tf\t*[0-9]`, "reported coverage for assembly function f") } +// Issue 24588. +func TestCoverageDashC(t *testing.T) { + skipIfGccgo(t, "gccgo has no cover tool") + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.makeTempdir() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("test", "-c", "-o", tg.path("coverdep"), "-coverprofile="+tg.path("no/such/dir/cover.out"), "coverdep") + tg.wantExecutable(tg.path("coverdep"), "go -test -c -coverprofile did not create executable") +} + func TestPluginNonMain(t *testing.T) { wd, err := os.Getwd() if err != nil { @@ -2845,7 +2814,7 @@ func TestCgoPkgConfig(t *testing.T) { // OpenBSD's pkg-config is strict about whitespace and only // supports backslash-escaped whitespace. It does not support // quotes, which the normal freedesktop.org pkg-config does - // support. See http://man.openbsd.org/pkg-config.1 + // support. See https://man.openbsd.org/pkg-config.1 tg.tempFile("foo.pc", ` Name: foo Description: The foo library @@ -3048,11 +3017,25 @@ func TestBuildDashIInstallsDependencies(t *testing.T) { checkbar("cmd") } -func TestGoBuildInTestOnlyDirectoryFailsWithAGoodError(t *testing.T) { +func TestGoBuildTestOnly(t *testing.T) { tg := testgo(t) defer tg.cleanup() - tg.runFail("build", "./testdata/testonly") - tg.grepStderr("no non-test Go files in", "go build ./testdata/testonly produced unexpected error") + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + tg.tempFile("src/testonly/t_test.go", `package testonly`) + tg.tempFile("src/testonly2/t.go", `package testonly2`) + tg.cd(tg.path("src")) + + // Named explicitly, test-only packages should be reported as unbuildable/uninstallable, + // even if there is a wildcard also matching. + tg.runFail("build", "testonly", "testonly...") + tg.grepStderr("no non-test Go files in", "go build ./xtestonly produced unexpected error") + tg.runFail("install", "./testonly") + tg.grepStderr("no non-test Go files in", "go install ./testonly produced unexpected error") + + // Named through a wildcards, the test-only packages should be silently ignored. + tg.run("build", "testonly...") + tg.run("install", "./testonly...") } func TestGoTestDetectsTestOnlyImportCycles(t *testing.T) { @@ -3088,6 +3071,9 @@ func TestGoTestMainAsNormalTest(t *testing.T) { } func TestGoTestMainTwice(t *testing.T) { + if testing.Short() { + t.Skip("Skipping in short mode") + } tg := testgo(t) defer tg.cleanup() tg.makeTempdir() @@ -3182,6 +3168,22 @@ func TestGoGenerateEnv(t *testing.T) { } } +func TestGoGenerateXTestPkgName(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("skipping because windows has no echo command") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("env_test.go", "package main_test\n\n//go:generate echo $GOPACKAGE") + tg.run("generate", tg.path("env_test.go")) + want := "main_test" + if got := strings.TrimSpace(tg.getStdout()); got != want { + t.Errorf("go generate in XTest file got package name %q; want %q", got, want) + } +} + func TestGoGenerateBadImports(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("skipping because windows has no echo command") @@ -3549,24 +3551,43 @@ func TestImportLocal(t *testing.T) { } func TestGoGetInsecure(t *testing.T) { - testenv.MustHaveExternalNetwork(t) + test := func(t *testing.T, modules bool) { + testenv.MustHaveExternalNetwork(t) - tg := testgo(t) - defer tg.cleanup() - tg.makeTempdir() - tg.setenv("GOPATH", tg.path(".")) - tg.failSSH() + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.failSSH() - const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p" + if modules { + tg.setenv("GOPATH", tg.path("gp")) + tg.tempFile("go.mod", "module m") + tg.cd(tg.path(".")) + tg.setenv("GO111MODULE", "on") + } else { + tg.setenv("GOPATH", tg.path(".")) + tg.setenv("GO111MODULE", "off") + } - // Try go get -d of HTTP-only repo (should fail). - tg.runFail("get", "-d", repo) + const repo = "insecure.go-get-issue-15410.appspot.com/pkg/p" - // Try again with -insecure (should succeed). - tg.run("get", "-d", "-insecure", repo) + // Try go get -d of HTTP-only repo (should fail). + tg.runFail("get", "-d", repo) - // Try updating without -insecure (should fail). - tg.runFail("get", "-d", "-u", "-f", repo) + // Try again with -insecure (should succeed). + tg.run("get", "-d", "-insecure", repo) + + // Try updating without -insecure (should fail). + tg.runFail("get", "-d", "-u", "-f", repo) + + if modules { + tg.run("list", "-m", "...") + tg.grepStdout("insecure.go-get-issue", "should find insecure module") + } + } + + t.Run("gopath", func(t *testing.T) { test(t, false) }) + t.Run("modules", func(t *testing.T) { test(t, true) }) } func TestGoGetUpdateInsecure(t *testing.T) { @@ -3593,6 +3614,40 @@ func TestGoGetUpdateInsecure(t *testing.T) { tg.run("get", "-d", "-u", "-f", "-insecure", pkg) } +func TestGoGetUpdateUnknownProtocol(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path(".")) + + const repo = "github.com/golang/example" + + // Clone the repo via HTTPS manually. + repoDir := tg.path("src/" + repo) + cmd := exec.Command("git", "clone", "-q", "https://"+repo, repoDir) + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("cloning %v repo: %v\n%s", repo, err, out) + } + + // Configure the repo to use a protocol unknown to cmd/go + // that still actually works. + cmd = exec.Command("git", "remote", "set-url", "origin", "xyz://"+repo) + cmd.Dir = repoDir + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("git remote set-url: %v\n%s", err, out) + } + cmd = exec.Command("git", "config", "--local", "url.https://github.com/.insteadOf", "xyz://github.com/") + cmd.Dir = repoDir + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("git config: %v\n%s", err, out) + } + + // We need -f to ignore import comments. + tg.run("get", "-d", "-u", "-f", repo+"/hello") +} + func TestGoGetInsecureCustomDomain(t *testing.T) { testenv.MustHaveExternalNetwork(t) @@ -4175,9 +4230,10 @@ func TestGoGetUpdateWithWildcard(t *testing.T) { tg.setenv("GOPATH", tg.path(".")) const aPkgImportPath = "github.com/tmwh/go-get-issue-14450/a" tg.run("get", aPkgImportPath) - tg.run("get", "-u", ".../") - tg.grepStderrNot("cannot find package", "did not update packages given wildcard path") + tg.runFail("get", "-u", ".../") + tg.grepStderr("cannot find package.*d-dependency/e", "should have detected e missing") + // Even though get -u failed, the source for others should be downloaded. var expectedPkgPaths = []string{ "src/github.com/tmwh/go-get-issue-14450/b", "src/github.com/tmwh/go-get-issue-14450-b-dependency/c", @@ -4754,7 +4810,7 @@ func main() {}`) before() tg.run("install", "mycmd") after() - tg.wantStale("mycmd", "stale dependency: runtime/internal/sys", "should be stale after environment variable change") + tg.wantStale("mycmd", "stale dependency", "should be stale after environment variable change") } } @@ -4795,34 +4851,34 @@ func TestTestRegexps(t *testing.T) { // BenchmarkX/Y is run in full, twice want := `=== RUN TestX === RUN TestX/Y - x_test.go:6: LOG: X running - x_test.go:8: LOG: Y running + x_test.go:6: LOG: X running + x_test.go:8: LOG: Y running === RUN TestXX - z_test.go:10: LOG: XX running + z_test.go:10: LOG: XX running === RUN TestX === RUN TestX/Y - x_test.go:6: LOG: X running - x_test.go:8: LOG: Y running + x_test.go:6: LOG: X running + x_test.go:8: LOG: Y running === RUN TestXX - z_test.go:10: LOG: XX running + z_test.go:10: LOG: XX running --- BENCH: BenchmarkX/Y - x_test.go:15: LOG: Y running N=1 - x_test.go:15: LOG: Y running N=100 - x_test.go:15: LOG: Y running N=10000 - x_test.go:15: LOG: Y running N=1000000 - x_test.go:15: LOG: Y running N=100000000 - x_test.go:15: LOG: Y running N=2000000000 + x_test.go:15: LOG: Y running N=1 + x_test.go:15: LOG: Y running N=100 + x_test.go:15: LOG: Y running N=10000 + x_test.go:15: LOG: Y running N=1000000 + x_test.go:15: LOG: Y running N=100000000 + x_test.go:15: LOG: Y running N=2000000000 --- BENCH: BenchmarkX/Y - x_test.go:15: LOG: Y running N=1 - x_test.go:15: LOG: Y running N=100 - x_test.go:15: LOG: Y running N=10000 - x_test.go:15: LOG: Y running N=1000000 - x_test.go:15: LOG: Y running N=100000000 - x_test.go:15: LOG: Y running N=2000000000 + x_test.go:15: LOG: Y running N=1 + x_test.go:15: LOG: Y running N=100 + x_test.go:15: LOG: Y running N=10000 + x_test.go:15: LOG: Y running N=1000000 + x_test.go:15: LOG: Y running N=100000000 + x_test.go:15: LOG: Y running N=2000000000 --- BENCH: BenchmarkX - x_test.go:13: LOG: X running N=1 + x_test.go:13: LOG: X running N=1 --- BENCH: BenchmarkXX - z_test.go:18: LOG: XX running N=1 + z_test.go:18: LOG: XX running N=1 ` have := strings.Join(lines, "") @@ -4857,7 +4913,8 @@ func TestBuildmodePIE(t *testing.T) { platform := fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH) switch platform { case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x", - "android/amd64", "android/arm", "android/arm64", "android/386": + "android/amd64", "android/arm", "android/arm64", "android/386", + "freebsd/amd64": case "darwin/amd64": default: t.Skipf("skipping test because buildmode=pie is not supported on %s", platform) @@ -4872,7 +4929,7 @@ func TestBuildmodePIE(t *testing.T) { tg.run("build", "-buildmode=pie", "-o", obj, src) switch runtime.GOOS { - case "linux", "android": + case "linux", "android", "freebsd": f, err := elf.Open(obj) if err != nil { t.Fatal(err) @@ -4983,7 +5040,8 @@ func TestWrongGOOSErrorBeforeLoadError(t *testing.T) { } func TestUpxCompression(t *testing.T) { - if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { + if runtime.GOOS != "linux" || + (runtime.GOARCH != "amd64" && runtime.GOARCH != "386") { t.Skipf("skipping upx test on %s/%s", runtime.GOOS, runtime.GOARCH) } @@ -5036,79 +5094,47 @@ func TestUpxCompression(t *testing.T) { } } -func TestGOTMPDIR(t *testing.T) { +// Test that Go binaries can be run under QEMU in user-emulation mode +// (See issue #13024). +func TestQEMUUserMode(t *testing.T) { + if testing.Short() && testenv.Builder() == "" { + t.Skipf("skipping in -short mode on non-builder") + } + + testArchs := []struct { + g, qemu string + }{ + {"arm", "arm"}, + {"arm64", "aarch64"}, + } + tg := testgo(t) defer tg.cleanup() + tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello qemu-user") }`) tg.parallel() - tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) - tg.makeTempdir() - tg.setenv("GOTMPDIR", tg.tempdir) - tg.setenv("GOCACHE", "off") + src, obj := tg.path("main.go"), tg.path("main") - // complex/x is a trivial non-main package. - tg.run("build", "-work", "-x", "complex/w") - tg.grepStderr("WORK="+regexp.QuoteMeta(tg.tempdir), "did not work in $GOTMPDIR") -} + for _, arch := range testArchs { + out, err := exec.Command("qemu-"+arch.qemu, "--version").CombinedOutput() + if err != nil { + t.Logf("Skipping %s test (qemu-%s not available)", arch.g, arch.qemu) + continue + } -func TestBuildCache(t *testing.T) { - tooSlow(t) - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { - t.Skip("GODEBUG gocacheverify") + tg.setenv("GOARCH", arch.g) + tg.run("build", "-o", obj, src) + + out, err = exec.Command("qemu-"+arch.qemu, obj).CombinedOutput() + if err != nil { + t.Logf("qemu-%s output:\n%s\n", arch.qemu, out) + t.Errorf("qemu-%s failed with %v", arch.qemu, err) + continue + } + if want := "hello qemu-user"; string(out) != want { + t.Errorf("bad output from qemu-%s:\ngot %s; want %s", arch.qemu, out, want) + } } - tg := testgo(t) - defer tg.cleanup() - tg.parallel() - tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) - tg.makeTempdir() - tg.setenv("GOCACHE", tg.tempdir) - // complex/w is a trivial non-main package. - // It imports nothing, so there should be no Deps. - tg.run("list", "-f={{join .Deps \" \"}}", "complex/w") - tg.grepStdoutNot(".+", "complex/w depends on unexpected packages") - - tg.run("build", "-x", "complex/w") - tg.grepStderr(`[\\/]compile|gccgo`, "did not run compiler") - - tg.run("build", "-x", "complex/w") - tg.grepStderrNot(`[\\/]compile|gccgo`, "ran compiler incorrectly") - - tg.run("build", "-a", "-x", "complex/w") - tg.grepStderr(`[\\/]compile|gccgo`, "did not run compiler with -a") - - // complex is a non-trivial main package. - // the link step should not be cached. - tg.run("build", "-o", os.DevNull, "-x", "complex") - tg.grepStderr(`[\\/]link|gccgo`, "did not run linker") - - tg.run("build", "-o", os.DevNull, "-x", "complex") - tg.grepStderr(`[\\/]link|gccgo`, "did not run linker") -} - -func TestCacheOutput(t *testing.T) { - // Test that command output is cached and replayed too. - if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { - t.Skip("GODEBUG gocacheverify") - } - tg := testgo(t) - defer tg.cleanup() - tg.parallel() - tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) - tg.makeTempdir() - tg.setenv("GOCACHE", tg.tempdir) - - tg.run("build", "-gcflags=-m", "errors") - stdout1 := tg.getStdout() - stderr1 := tg.getStderr() - - tg.run("build", "-gcflags=-m", "errors") - stdout2 := tg.getStdout() - stderr2 := tg.getStderr() - - if stdout2 != stdout1 || stderr2 != stderr1 { - t.Errorf("cache did not reproduce output:\n\nstdout1:\n%s\n\nstdout2:\n%s\n\nstderr1:\n%s\n\nstderr2:\n%s", - stdout1, stdout2, stderr1, stderr2) - } } func TestCacheListStale(t *testing.T) { @@ -5151,6 +5177,32 @@ func TestCacheCoverage(t *testing.T) { tg.run("test", "-cover", "-short", "math", "strings") } +func TestCacheVet(t *testing.T) { + skipIfGccgo(t, "gccgo has no standard packages") + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") { + t.Skip("GODEBUG gocacheverify") + } + if os.Getenv("GOCACHE") == "off" { + tooSlow(t) + tg.makeTempdir() + tg.setenv("GOCACHE", tg.path("cache")) + } + + // Check that second vet reuses cgo-derived inputs. + // The first command could be build instead of vet, + // except that if the cache is empty and there's a net.a + // in GOROOT/pkg, the build will not bother to regenerate + // and cache the cgo outputs, whereas vet always will. + tg.run("vet", "os/user") + tg.run("vet", "-x", "os/user") + tg.grepStderrNot(`^(clang|gcc)`, "should not have run compiler") + tg.grepStderrNot(`[\\/]cgo `, "should not have run cgo") +} + func TestIssue22588(t *testing.T) { // Don't get confused by stderr coming from tools. tg := testgo(t) @@ -5241,14 +5293,14 @@ func TestTestCache(t *testing.T) { // timeout here should not affect result being cached // or being retrieved later. tg.run("test", "-x", "-timeout=10s", "errors") - tg.grepStderr(`[\\/](compile|gccgo) `, "did not run compiler") - tg.grepStderr(`[\\/](link|gccgo) `, "did not run linker") + tg.grepStderr(`[\\/]compile|gccgo`, "did not run compiler") + tg.grepStderr(`[\\/]link|gccgo`, "did not run linker") tg.grepStderr(`errors\.test`, "did not run test") tg.run("test", "-x", "errors") tg.grepStdout(`ok \terrors\t\(cached\)`, "did not report cached result") - tg.grepStderrNot(`[\\/](compile|gccgo) `, "incorrectly ran compiler") - tg.grepStderrNot(`[\\/](link|gccgo) `, "incorrectly ran linker") + tg.grepStderrNot(`[\\/]compile|gccgo`, "incorrectly ran compiler") + tg.grepStderrNot(`[\\/]link|gccgo`, "incorrectly ran linker") tg.grepStderrNot(`errors\.test`, "incorrectly ran test") tg.grepStderrNot("DO NOT USE", "poisoned action status leaked") @@ -5520,9 +5572,29 @@ func TestTestVet(t *testing.T) { tg.runFail("test", "vetfail/...") tg.grepStderr(`Printf format %d`, "did not diagnose bad Printf") tg.grepStdout(`ok\s+vetfail/p2`, "did not run vetfail/p2") + + // Use -a so that we need to recompute the vet-specific export data for + // vetfail/p1. + tg.run("test", "-a", "vetfail/p2") + tg.grepStderrNot(`invalid.*constraint`, "did diagnose bad build constraint in vetxonly mode") } -func TestTestRebuild(t *testing.T) { +func TestTestSkipVetAfterFailedBuild(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + tg.tempFile("x_test.go", `package x + func f() { + return 1 + } + `) + + tg.runFail("test", tg.path("x_test.go")) + tg.grepStderrNot(`vet`, "vet should be skipped after the failed build") +} + +func TestTestVetRebuild(t *testing.T) { tg := testgo(t) defer tg.cleanup() tg.parallel() @@ -5558,6 +5630,7 @@ func TestTestRebuild(t *testing.T) { tg.setenv("GOPATH", tg.path(".")) tg.run("test", "b") + tg.run("vet", "b") } func TestInstallDeps(t *testing.T) { @@ -5619,37 +5692,6 @@ func TestRelativePkgdir(t *testing.T) { tg.run("build", "-i", "-pkgdir=.", "runtime") } -func TestGcflagsPatterns(t *testing.T) { - skipIfGccgo(t, "gccgo has no standard packages") - tg := testgo(t) - defer tg.cleanup() - tg.setenv("GOPATH", "") - tg.setenv("GOCACHE", "off") - - tg.run("build", "-n", "-v", "-gcflags= \t\r\n -e", "fmt") - tg.grepStderr("^# fmt", "did not rebuild fmt") - tg.grepStderrNot("^# reflect", "incorrectly rebuilt reflect") - - tg.run("build", "-n", "-v", "-gcflags=-e", "fmt", "reflect") - tg.grepStderr("^# fmt", "did not rebuild fmt") - tg.grepStderr("^# reflect", "did not rebuild reflect") - tg.grepStderrNot("^# runtime", "incorrectly rebuilt runtime") - - tg.run("build", "-n", "-x", "-v", "-gcflags= \t\r\n reflect \t\r\n = \t\r\n -N", "fmt") - tg.grepStderr("^# fmt", "did not rebuild fmt") - tg.grepStderr("^# reflect", "did not rebuild reflect") - tg.grepStderr("compile.* -N .*-p reflect", "did not build reflect with -N flag") - tg.grepStderrNot("compile.* -N .*-p fmt", "incorrectly built fmt with -N flag") - - tg.run("test", "-c", "-n", "-gcflags=-N", "-ldflags=-X=x.y=z", "strings") - tg.grepStderr("compile.* -N .*compare_test.go", "did not compile strings_test package with -N flag") - tg.grepStderr("link.* -X=x.y=z", "did not link strings.test binary with -X flag") - - tg.run("test", "-c", "-n", "-gcflags=strings=-N", "-ldflags=strings=-X=x.y=z", "strings") - tg.grepStderr("compile.* -N .*compare_test.go", "did not compile strings_test package with -N flag") - tg.grepStderr("link.* -X=x.y=z", "did not link strings.test binary with -X flag") -} - func TestGoTestMinusN(t *testing.T) { // Intent here is to verify that 'go test -n' works without crashing. // This reuses flag_test.go, but really any test would do. @@ -5726,6 +5768,9 @@ func TestFailFast(t *testing.T) { // non-parallel subtests: {"TestFailingSubtestsA", true, 1}, {"TestFailingSubtestsA", false, 2}, + // fatal test + {"TestFatal[CD]", true, 1}, + {"TestFatal[CD]", false, 2}, } for _, tt := range tests { @@ -5789,59 +5834,6 @@ func init() {} tg.run("test", "a") } -// Issue 23150. -func TestCpuprofileTwice(t *testing.T) { - tg := testgo(t) - defer tg.cleanup() - tg.parallel() - tg.tempFile("prof/src/x/x_test.go", ` - package x_test - import ( - "testing" - "time" - ) - func TestSleep(t *testing.T) { time.Sleep(10 * time.Millisecond) }`) - tg.setenv("GOPATH", tg.path("prof")) - bin := tg.path("x.test") - out := tg.path("cpu.out") - tg.run("test", "-o="+bin, "-cpuprofile="+out, "x") - tg.must(os.Remove(out)) - tg.run("test", "-o="+bin, "-cpuprofile="+out, "x") - tg.mustExist(out) -} - -// Issue 23694. -func TestAtomicCoverpkgAll(t *testing.T) { - skipIfGccgo(t, "gccgo has no cover tool") - tg := testgo(t) - defer tg.cleanup() - tg.parallel() - - tg.tempFile("src/x/x.go", `package x; import _ "sync/atomic"; func F() {}`) - tg.tempFile("src/x/x_test.go", `package x; import "testing"; func TestF(t *testing.T) { F() }`) - tg.setenv("GOPATH", tg.path(".")) - tg.run("test", "-coverpkg=all", "-covermode=atomic", "x") - if canRace { - tg.run("test", "-coverpkg=all", "-race", "x") - } -} - -// Issue 23882. -func TestCoverpkgAllRuntime(t *testing.T) { - skipIfGccgo(t, "gccgo has no cover tool") - tg := testgo(t) - defer tg.cleanup() - tg.parallel() - - tg.tempFile("src/x/x.go", `package x; import _ "runtime"; func F() {}`) - tg.tempFile("src/x/x_test.go", `package x; import "testing"; func TestF(t *testing.T) { F() }`) - tg.setenv("GOPATH", tg.path(".")) - tg.run("test", "-coverpkg=all", "x") - if canRace { - tg.run("test", "-coverpkg=all", "-race", "x") - } -} - func TestBadCommandLines(t *testing.T) { tg := testgo(t) defer tg.cleanup() @@ -5871,12 +5863,12 @@ func TestBadCommandLines(t *testing.T) { tg.tempFile("src/@x/x.go", "package x\n") tg.setenv("GOPATH", tg.path(".")) tg.runFail("build", "@x") - tg.grepStderr("invalid input directory name \"@x\"", "did not reject @x directory") + tg.grepStderr("invalid input directory name \"@x\"|cannot use path@version syntax", "did not reject @x directory") tg.tempFile("src/@x/y/y.go", "package y\n") tg.setenv("GOPATH", tg.path(".")) tg.runFail("build", "@x/y") - tg.grepStderr("invalid import path \"@x/y\"", "did not reject @x/y import path") + tg.grepStderr("invalid import path \"@x/y\"|cannot use path@version syntax", "did not reject @x/y import path") tg.tempFile("src/-x/x.go", "package x\n") tg.setenv("GOPATH", tg.path(".")) @@ -6032,3 +6024,198 @@ echo $* >>`+tg.path("pkg-config.out")) t.Errorf("got %q want %q", out, want) } } + +func TestCgoCache(t *testing.T) { + if !canCgo { + t.Skip("no cgo") + } + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/x/a.go", `package main + // #ifndef VAL + // #define VAL 0 + // #endif + // int val = VAL; + import "C" + import "fmt" + func main() { fmt.Println(C.val) } + `) + tg.setenv("GOPATH", tg.path(".")) + exe := tg.path("x.exe") + tg.run("build", "-o", exe, "x") + tg.setenv("CGO_LDFLAGS", "-lnosuchlibraryexists") + tg.runFail("build", "-o", exe, "x") + tg.grepStderr(`nosuchlibraryexists`, "did not run linker with changed CGO_LDFLAGS") +} + +// Issue 23982 +func TestFilepathUnderCwdFormat(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.run("test", "-x", "-cover", "log") + tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd") +} + +// Issue 24396. +func TestDontReportRemoveOfEmptyDir(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/a/a.go", `package a`) + tg.setenv("GOPATH", tg.path(".")) + tg.run("install", "-x", "a") + tg.run("install", "-x", "a") + // The second install should have printed only a WORK= line, + // nothing else. + if bytes.Count(tg.stdout.Bytes(), []byte{'\n'})+bytes.Count(tg.stderr.Bytes(), []byte{'\n'}) > 1 { + t.Error("unnecessary output when installing installed package") + } +} + +// Issue 23264. +func TestNoRelativeTmpdir(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + + tg.tempFile("src/a/a.go", `package a`) + tg.cd(tg.path(".")) + tg.must(os.Mkdir("tmp", 0777)) + + tg.setenv("GOCACHE", "off") + tg.setenv("GOPATH", tg.path(".")) + tg.setenv("GOTMPDIR", "tmp") + tg.run("build", "-work", "a") + tg.grepStderr("WORK=[^t]", "work should be absolute path") + + tg.unsetenv("GOTMPDIR") + tg.setenv("TMP", "tmp") // windows + tg.setenv("TMPDIR", "tmp") // unix + tg.run("build", "-work", "a") + tg.grepStderr("WORK=[^t]", "work should be absolute path") +} + +// Issue 24704. +func TestLinkerTmpDirIsDeleted(t *testing.T) { + skipIfGccgo(t, "gccgo does not use cmd/link") + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("a.go", `package main; import "C"; func main() {}`) + tg.run("build", "-ldflags", "-v", "-o", os.DevNull, tg.path("a.go")) + // Find line that has "host link:" in linker output. + stderr := tg.getStderr() + var hostLinkLine string + for _, line := range strings.Split(stderr, "\n") { + if !strings.Contains(line, "host link:") { + continue + } + hostLinkLine = line + break + } + if hostLinkLine == "" { + t.Fatal(`fail to find with "host link:" string in linker output`) + } + // Find parameter, like "/tmp/go-link-408556474/go.o" inside of + // "host link:" line, and extract temp directory /tmp/go-link-408556474 + // out of it. + tmpdir := hostLinkLine + i := strings.Index(tmpdir, `go.o"`) + if i == -1 { + t.Fatalf(`fail to find "go.o" in "host link:" line %q`, hostLinkLine) + } + tmpdir = tmpdir[:i-1] + i = strings.LastIndex(tmpdir, `"`) + if i == -1 { + t.Fatalf(`fail to find " in "host link:" line %q`, hostLinkLine) + } + tmpdir = tmpdir[i+1:] + // Verify that temp directory has been removed. + _, err := os.Stat(tmpdir) + if err == nil { + t.Fatalf("temp directory %q has not been removed", tmpdir) + } + if !os.IsNotExist(err) { + t.Fatalf("Stat(%q) returns unexpected error: %v", tmpdir, err) + } +} + +func testCDAndGOPATHAreDifferent(tg *testgoData, cd, gopath string) { + skipIfGccgo(tg.t, "gccgo does not support -ldflags -X") + tg.setenv("GOPATH", gopath) + + tg.tempDir("dir") + exe := tg.path("dir/a.exe") + + tg.cd(cd) + + tg.run("build", "-o", exe, "-ldflags", "-X=my.pkg.Text=linkXworked") + out, err := exec.Command(exe).CombinedOutput() + if err != nil { + tg.t.Fatal(err) + } + if string(out) != "linkXworked\n" { + tg.t.Errorf(`incorrect output with GOPATH=%q and CD=%q: expected "linkXworked\n", but have %q`, gopath, cd, string(out)) + } +} + +func TestCDAndGOPATHAreDifferent(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + + gopath := filepath.Join(tg.pwd(), "testdata") + cd := filepath.Join(gopath, "src/my.pkg/main") + + testCDAndGOPATHAreDifferent(tg, cd, gopath) + if runtime.GOOS == "windows" { + testCDAndGOPATHAreDifferent(tg, cd, strings.Replace(gopath, `\`, `/`, -1)) + testCDAndGOPATHAreDifferent(tg, cd, strings.ToUpper(gopath)) + testCDAndGOPATHAreDifferent(tg, cd, strings.ToLower(gopath)) + } +} + +// Issue 26242. +func TestGoTestWithoutTests(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("test", "testnorun") + tg.grepStdout(`testnorun\t\[no test files\]`, "do not want test to run") +} + +// Issue 25579. +func TestGoBuildDashODevNull(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata")) + tg.run("build", "-o", os.DevNull, filepath.Join(tg.pwd(), "testdata", "src", "hello", "hello.go")) + tg.mustNotExist("hello") + tg.mustNotExist("hello.exe") +} + +// Issue 25093. +func TestCoverpkgTestOnly(t *testing.T) { + skipIfGccgo(t, "gccgo has no cover tool") + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + tg.tempFile("src/a/a.go", `package a + func F(i int) int { + return i*i + }`) + tg.tempFile("src/atest/a_test.go", ` + package a_test + import ( "a"; "testing" ) + func TestF(t *testing.T) { a.F(2) } + `) + tg.setenv("GOPATH", tg.path(".")) + tg.run("test", "-coverpkg=a", "atest") + tg.grepStderrNot("no packages being tested depend on matches", "bad match message") + tg.grepStdout("coverage: 100", "no coverage") +} diff --git a/libgo/go/cmd/go/go_windows_test.go b/libgo/go/cmd/go/go_windows_test.go index aa68a195802..99af3d43dcc 100644 --- a/libgo/go/cmd/go/go_windows_test.go +++ b/libgo/go/cmd/go/go_windows_test.go @@ -12,7 +12,6 @@ import ( "os/exec" "path/filepath" "strings" - "syscall" "testing" ) @@ -57,15 +56,6 @@ func TestAbsolutePath(t *testing.T) { } } -func isWindowsXP(t *testing.T) bool { - v, err := syscall.GetVersion() - if err != nil { - t.Fatalf("GetVersion failed: %v", err) - } - major := byte(v) - return major < 6 -} - func runIcacls(t *testing.T, args ...string) string { t.Helper() out, err := exec.Command("icacls", args...).CombinedOutput() @@ -89,10 +79,6 @@ func runGetACL(t *testing.T, path string) string { // has discretionary access control list (DACL) set as if the file // was created in the destination directory. func TestACL(t *testing.T) { - if isWindowsXP(t) { - t.Skip("Windows XP does not have powershell command") - } - tmpdir, err := ioutil.TempDir("", "TestACL") if err != nil { t.Fatal(err) @@ -111,7 +97,7 @@ func TestACL(t *testing.T) { // will make all files created in TestACL/tmp have different // security attributes to the files created in TestACL. runIcacls(t, newtmpdir, - "/grant", "guest:(oi)(ci)f", // add Guest user to have full access + "/grant", "*S-1-5-32-546:(oi)(ci)f", // add Guests group to have full access ) src := filepath.Join(tmpdir, "main.go") diff --git a/libgo/go/cmd/go/internal/base/base.go b/libgo/go/cmd/go/internal/base/base.go index 286efbc0410..e7f54c9a365 100644 --- a/libgo/go/cmd/go/internal/base/base.go +++ b/libgo/go/cmd/go/internal/base/base.go @@ -45,25 +45,43 @@ type Command struct { // CustomFlags indicates that the command will do its own // flag parsing. CustomFlags bool + + // Commands lists the available commands and help topics. + // The order here is the order in which they are printed by 'go help'. + // Note that subcommands are in general best avoided. + Commands []*Command } -// Commands lists the available commands and help topics. -// The order here is the order in which they are printed by 'go help'. -var Commands []*Command +var Go = &Command{ + UsageLine: "go", + Long: `Go is a tool for managing Go source code.`, + // Commands initialized in package main +} -// Name returns the command's name: the first word in the usage line. -func (c *Command) Name() string { +// LongName returns the command's long name: all the words in the usage line between "go" and a flag or argument, +func (c *Command) LongName() string { name := c.UsageLine - i := strings.Index(name, " ") - if i >= 0 { + if i := strings.Index(name, " ["); i >= 0 { name = name[:i] } + if name == "go" { + return "" + } + return strings.TrimPrefix(name, "go ") +} + +// Name returns the command's short name: the last word in the usage line before a flag or argument. +func (c *Command) Name() string { + name := c.LongName() + if i := strings.LastIndex(name, " "); i >= 0 { + name = name[i+1:] + } return name } func (c *Command) Usage() { fmt.Fprintf(os.Stderr, "usage: %s\n", c.UsageLine) - fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", c.Name()) + fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", c.LongName()) os.Exit(2) } diff --git a/libgo/go/cmd/go/internal/base/goflags.go b/libgo/go/cmd/go/internal/base/goflags.go new file mode 100644 index 00000000000..2f50b50bfcf --- /dev/null +++ b/libgo/go/cmd/go/internal/base/goflags.go @@ -0,0 +1,152 @@ +// 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 base + +import ( + "flag" + "fmt" + "os" + "runtime" + "strings" + + "cmd/go/internal/cfg" +) + +var ( + goflags []string // cached $GOFLAGS list; can be -x or --x form + knownFlag = make(map[string]bool) // flags allowed to appear in $GOFLAGS; no leading dashes +) + +// AddKnownFlag adds name to the list of known flags for use in $GOFLAGS. +func AddKnownFlag(name string) { + knownFlag[name] = true +} + +// GOFLAGS returns the flags from $GOFLAGS. +// The list can be assumed to contain one string per flag, +// with each string either beginning with -name or --name. +func GOFLAGS() []string { + InitGOFLAGS() + return goflags +} + +// InitGOFLAGS initializes the goflags list from $GOFLAGS. +// If goflags is already initialized, it does nothing. +func InitGOFLAGS() { + if goflags != nil { // already initialized + return + } + + // Build list of all flags for all commands. + // If no command has that flag, then we report the problem. + // This catches typos while still letting users record flags in GOFLAGS + // that only apply to a subset of go commands. + // Commands using CustomFlags can report their flag names + // by calling AddKnownFlag instead. + var walkFlags func(*Command) + walkFlags = func(cmd *Command) { + for _, sub := range cmd.Commands { + walkFlags(sub) + } + cmd.Flag.VisitAll(func(f *flag.Flag) { + knownFlag[f.Name] = true + }) + } + walkFlags(Go) + + // Ignore bad flag in go env and go bug, because + // they are what people reach for when debugging + // a problem, and maybe they're debugging GOFLAGS. + // (Both will show the GOFLAGS setting if let succeed.) + hideErrors := cfg.CmdName == "env" || cfg.CmdName == "bug" + + goflags = strings.Fields(os.Getenv("GOFLAGS")) + if goflags == nil { + goflags = []string{} // avoid work on later InitGOFLAGS call + } + + // Each of the words returned by strings.Fields must be its own flag. + // To set flag arguments use -x=value instead of -x value. + // For boolean flags, -x is fine instead of -x=true. + for _, f := range goflags { + // Check that every flag looks like -x --x -x=value or --x=value. + if !strings.HasPrefix(f, "-") || f == "-" || f == "--" || strings.HasPrefix(f, "---") || strings.HasPrefix(f, "-=") || strings.HasPrefix(f, "--=") { + if hideErrors { + continue + } + Fatalf("go: parsing $GOFLAGS: non-flag %q", f) + } + + name := f[1:] + if name[0] == '-' { + name = name[1:] + } + if i := strings.Index(name, "="); i >= 0 { + name = name[:i] + } + if !knownFlag[name] { + if hideErrors { + continue + } + Fatalf("go: parsing $GOFLAGS: unknown flag -%s", name) + } + } +} + +// boolFlag is the optional interface for flag.Value known to the flag package. +// (It is not clear why package flag does not export this interface.) +type boolFlag interface { + flag.Value + IsBoolFlag() bool +} + +// SetFromGOFLAGS sets the flags in the given flag set using settings in $GOFLAGS. +func SetFromGOFLAGS(flags flag.FlagSet) { + InitGOFLAGS() + + // This loop is similar to flag.Parse except that it ignores + // unknown flags found in goflags, so that setting, say, GOFLAGS=-ldflags=-w + // does not break commands that don't have a -ldflags. + // It also adjusts the output to be clear that the reported problem is from $GOFLAGS. + where := "$GOFLAGS" + if runtime.GOOS == "windows" { + where = "%GOFLAGS%" + } + for _, goflag := range goflags { + name, value, hasValue := goflag, "", false + if i := strings.Index(goflag, "="); i >= 0 { + name, value, hasValue = goflag[:i], goflag[i+1:], true + } + if strings.HasPrefix(name, "--") { + name = name[1:] + } + f := flags.Lookup(name[1:]) + if f == nil { + continue + } + if fb, ok := f.Value.(boolFlag); ok && fb.IsBoolFlag() { + if hasValue { + if err := fb.Set(value); err != nil { + fmt.Fprintf(flags.Output(), "go: invalid boolean value %q for flag %s (from %s): %v\n", value, name, where, err) + flags.Usage() + } + } else { + if err := fb.Set("true"); err != nil { + fmt.Fprintf(flags.Output(), "go: invalid boolean flag %s (from %s): %v\n", name, where, err) + flags.Usage() + } + } + } else { + if !hasValue { + fmt.Fprintf(flags.Output(), "go: flag needs an argument: %s (from %s)\n", name, where) + flags.Usage() + } + if err := f.Value.Set(value); err != nil { + fmt.Fprintf(flags.Output(), "go: invalid value %q for flag %s (from %s): %v\n", value, name, where, err) + flags.Usage() + } + } + } +} diff --git a/libgo/go/cmd/go/internal/base/signal_unix.go b/libgo/go/cmd/go/internal/base/signal_unix.go index b90f3a2f191..c109eecadb3 100644 --- a/libgo/go/cmd/go/internal/base/signal_unix.go +++ b/libgo/go/cmd/go/internal/base/signal_unix.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. -// +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris +// +build aix darwin dragonfly freebsd js linux nacl 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 963da94c493..e701f6eac9c 100644 --- a/libgo/go/cmd/go/internal/bug/bug.go +++ b/libgo/go/cmd/go/internal/bug/bug.go @@ -25,7 +25,7 @@ import ( var CmdBug = &base.Command{ Run: runBug, - UsageLine: "bug", + UsageLine: "go bug", Short: "start a bug report", Long: ` Bug opens the default browser and starts a new bug report. @@ -38,6 +38,9 @@ func init() { } func runBug(cmd *base.Command, args []string) { + if len(args) > 0 { + base.Fatalf("go bug: bug takes no arguments") + } var buf bytes.Buffer buf.WriteString(bugHeader) inspectGoVersion(&buf) diff --git a/libgo/go/cmd/go/internal/cache/cache.go b/libgo/go/cmd/go/internal/cache/cache.go index edb58826f17..0cf01550ff9 100644 --- a/libgo/go/cmd/go/internal/cache/cache.go +++ b/libgo/go/cmd/go/internal/cache/cache.go @@ -189,6 +189,21 @@ func (c *Cache) get(id ActionID) (Entry, error) { return Entry{buf, size, time.Unix(0, tm)}, nil } +// GetFile looks up the action ID in the cache and returns +// the name of the corresponding data file. +func (c *Cache) GetFile(id ActionID) (file string, entry Entry, err error) { + entry, err = c.Get(id) + if err != nil { + return "", Entry{}, err + } + file = c.OutputFile(entry.OutputID) + info, err := os.Stat(file) + if err != nil || info.Size() != entry.Size { + return "", Entry{}, errMissing + } + return file, entry, nil +} + // GetBytes looks up the action ID in the cache and returns // the corresponding output bytes. // GetBytes should only be used for data that can be expected to fit in memory. diff --git a/libgo/go/cmd/go/internal/cache/default.go b/libgo/go/cmd/go/internal/cache/default.go index 97283762258..02fc1e896f7 100644 --- a/libgo/go/cmd/go/internal/cache/default.go +++ b/libgo/go/cmd/go/internal/cache/default.go @@ -35,12 +35,14 @@ See golang.org to learn more about Go. // initDefaultCache does the work of finding the default cache // the first time Default is called. func initDefaultCache() { - dir := DefaultDir() + dir, showWarnings := defaultDir() if dir == "off" { return } if err := os.MkdirAll(dir, 0777); err != nil { - fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err) + if showWarnings { + fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err) + } return } if _, err := os.Stat(filepath.Join(dir, "README")); err != nil { @@ -50,7 +52,9 @@ func initDefaultCache() { c, err := Open(dir) if err != nil { - fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err) + if showWarnings { + fmt.Fprintf(os.Stderr, "go: disabling cache (%s) due to initialization failure: %s\n", dir, err) + } return } defaultCache = c @@ -59,14 +63,24 @@ func initDefaultCache() { // DefaultDir returns the effective GOCACHE setting. // It returns "off" if the cache is disabled. func DefaultDir() string { + dir, _ := defaultDir() + return dir +} + +// defaultDir returns the effective GOCACHE setting. +// It returns "off" if the cache is disabled. +// The second return value reports whether warnings should +// be shown if the cache fails to initialize. +func defaultDir() (string, bool) { dir := os.Getenv("GOCACHE") if dir != "" { - return dir + return dir, true } // Compute default location. // TODO(rsc): This code belongs somewhere else, // like maybe ioutil.CacheDir or os.CacheDir. + showWarnings := true switch runtime.GOOS { case "windows": dir = os.Getenv("LocalAppData") @@ -76,20 +90,20 @@ func DefaultDir() string { dir = os.Getenv("AppData") } if dir == "" { - return "off" + return "off", true } case "darwin": dir = os.Getenv("HOME") if dir == "" { - return "off" + return "off", true } dir += "/Library/Caches" case "plan9": dir = os.Getenv("home") if dir == "" { - return "off" + return "off", true } // Plan 9 has no established per-user cache directory, // but $home/lib/xyz is the usual equivalent of $HOME/.xyz on Unix. @@ -101,10 +115,15 @@ func DefaultDir() string { if dir == "" { dir = os.Getenv("HOME") if dir == "" { - return "off" + return "off", true + } + if dir == "/" { + // probably docker run with -u flag + // https://golang.org/issue/26280 + showWarnings = false } dir += "/.cache" } } - return filepath.Join(dir, "go-build") + return filepath.Join(dir, "go-build"), showWarnings } diff --git a/libgo/go/cmd/go/internal/cache/default_unix_test.go b/libgo/go/cmd/go/internal/cache/default_unix_test.go new file mode 100644 index 00000000000..a207497a42c --- /dev/null +++ b/libgo/go/cmd/go/internal/cache/default_unix_test.go @@ -0,0 +1,67 @@ +// 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 !windows,!darwin,!plan9 + +package cache + +import ( + "os" + "strings" + "testing" +) + +func TestDefaultDir(t *testing.T) { + goCacheDir := "/tmp/test-go-cache" + xdgCacheDir := "/tmp/test-xdg-cache" + homeDir := "/tmp/test-home" + + // undo env changes when finished + defer func(GOCACHE, XDG_CACHE_HOME, HOME string) { + os.Setenv("GOCACHE", GOCACHE) + os.Setenv("XDG_CACHE_HOME", XDG_CACHE_HOME) + os.Setenv("HOME", HOME) + }(os.Getenv("GOCACHE"), os.Getenv("XDG_CACHE_HOME"), os.Getenv("HOME")) + + os.Setenv("GOCACHE", goCacheDir) + os.Setenv("XDG_CACHE_HOME", xdgCacheDir) + os.Setenv("HOME", homeDir) + + dir, showWarnings := defaultDir() + if dir != goCacheDir { + t.Errorf("Cache DefaultDir %q should be $GOCACHE %q", dir, goCacheDir) + } + if !showWarnings { + t.Error("Warnings should be shown when $GOCACHE is set") + } + + os.Unsetenv("GOCACHE") + dir, showWarnings = defaultDir() + if !strings.HasPrefix(dir, xdgCacheDir+"/") { + t.Errorf("Cache DefaultDir %q should be under $XDG_CACHE_HOME %q when $GOCACHE is unset", dir, xdgCacheDir) + } + if !showWarnings { + t.Error("Warnings should be shown when $XDG_CACHE_HOME is set") + } + + os.Unsetenv("XDG_CACHE_HOME") + dir, showWarnings = defaultDir() + if !strings.HasPrefix(dir, homeDir+"/.cache/") { + t.Errorf("Cache DefaultDir %q should be under $HOME/.cache %q when $GOCACHE and $XDG_CACHE_HOME are unset", dir, homeDir+"/.cache") + } + if !showWarnings { + t.Error("Warnings should be shown when $HOME is not /") + } + + os.Unsetenv("HOME") + if dir, _ := defaultDir(); dir != "off" { + t.Error("Cache not disabled when $GOCACHE, $XDG_CACHE_HOME, and $HOME are unset") + } + + os.Setenv("HOME", "/") + if _, showWarnings := defaultDir(); showWarnings { + // https://golang.org/issue/26280 + t.Error("Cache initalization warnings should be squelched when $GOCACHE and $XDG_CACHE_HOME are unset and $HOME is /") + } +} diff --git a/libgo/go/cmd/go/internal/cfg/cfg.go b/libgo/go/cmd/go/internal/cfg/cfg.go index f0a2277d1b2..8dc4d1fbd29 100644 --- a/libgo/go/cmd/go/internal/cfg/cfg.go +++ b/libgo/go/cmd/go/internal/cfg/cfg.go @@ -20,7 +20,8 @@ import ( var ( BuildA bool // -a flag BuildBuildmode string // -buildmode flag - BuildContext = build.Default + BuildContext = defaultContext() + BuildMod string // -mod flag BuildI bool // -i flag BuildLinkshared bool // -linkshared flag BuildMSan bool // -msan flag @@ -42,6 +43,12 @@ var ( DebugActiongraph string // -debug-actiongraph flag (undocumented, unstable) ) +func defaultContext() build.Context { + ctxt := build.Default + ctxt.JoinPath = filepath.Join // back door to say "do not use go command" + return ctxt +} + func init() { BuildToolchainCompiler = func() string { return "missing-compiler" } BuildToolchainLinker = func() string { return "missing-linker" } @@ -67,6 +74,16 @@ var ( Goos = BuildContext.GOOS ExeSuffix string Gopath = filepath.SplitList(BuildContext.GOPATH) + + // ModulesEnabled specifies whether the go command is running + // in module-aware mode (as opposed to GOPATH mode). + // It is equal to modload.Enabled, but not all packages can import modload. + ModulesEnabled bool + + // GoModInGOPATH records whether we've found a go.mod in GOPATH/src + // in GO111MODULE=auto mode. In that case, we don't use modules + // but people might expect us to, so 'go get' warns. + GoModInGOPATH string ) func init() { @@ -84,9 +101,10 @@ var ( GOROOT_FINAL = findGOROOT_FINAL() // Used in envcmd.MkEnv and build ID computations. - GOARM = fmt.Sprint(objabi.GOARM) - GO386 = objabi.GO386 - GOMIPS = objabi.GOMIPS + GOARM = fmt.Sprint(objabi.GOARM) + GO386 = objabi.GO386 + GOMIPS = objabi.GOMIPS + GOMIPS64 = objabi.GOMIPS64 ) // Update build context to use our computed GOROOT. @@ -102,6 +120,16 @@ func init() { } } +// There is a copy of findGOROOT, isSameDir, and isGOROOT in +// x/tools/cmd/godoc/goroot.go. +// Try to keep them in sync for now. + +// findGOROOT returns the GOROOT value, using either an explicitly +// provided environment variable, a GOROOT that contains the current +// os.Executable value, or else the GOROOT that the binary was built +// with from runtime.GOROOT(). +// +// There is a copy of this code in x/tools/cmd/godoc/goroot.go. func findGOROOT() string { if env := os.Getenv("GOROOT"); env != "" { return filepath.Clean(env) @@ -161,6 +189,8 @@ func isSameDir(dir1, dir2 string) bool { // It does this by looking for the path/pkg/tool directory, // which is necessary for useful operation of the cmd/go tool, // and is not typically present in a GOPATH. +// +// There is a copy of this code in x/tools/cmd/godoc/goroot.go. func isGOROOT(path string) bool { stat, err := os.Stat(filepath.Join(path, "pkg", "tool")) if err != nil { diff --git a/libgo/go/cmd/go/internal/clean/clean.go b/libgo/go/cmd/go/internal/clean/clean.go index fa5af944af6..d023592eedc 100644 --- a/libgo/go/cmd/go/internal/clean/clean.go +++ b/libgo/go/cmd/go/internal/clean/clean.go @@ -17,11 +17,13 @@ import ( "cmd/go/internal/cache" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/modfetch" + "cmd/go/internal/modload" "cmd/go/internal/work" ) var CmdClean = &base.Command{ - UsageLine: "clean [-i] [-r] [-n] [-x] [-cache] [-testcache] [build flags] [packages]", + UsageLine: "go clean [clean flags] [build flags] [packages]", Short: "remove object files and cached files", Long: ` Clean removes object files from package source directories. @@ -65,6 +67,10 @@ The -cache flag causes clean to remove the entire go build cache. The -testcache flag causes clean to expire all test results in the go build cache. +The -modcache flag causes clean to remove the entire module +download cache, including unpacked source code of versioned +dependencies. + For more about build flags, see 'go help build'. For more about specifying packages, see 'go help packages'. @@ -75,6 +81,7 @@ var ( cleanI bool // clean -i flag cleanR bool // clean -r flag cleanCache bool // clean -cache flag + cleanModcache bool // clean -modcache flag cleanTestcache bool // clean -testcache flag ) @@ -85,6 +92,7 @@ func init() { CmdClean.Flag.BoolVar(&cleanI, "i", false, "") CmdClean.Flag.BoolVar(&cleanR, "r", false, "") CmdClean.Flag.BoolVar(&cleanCache, "cache", false, "") + CmdClean.Flag.BoolVar(&cleanModcache, "modcache", false, "") CmdClean.Flag.BoolVar(&cleanTestcache, "testcache", false, "") // -n and -x are important enough to be @@ -95,8 +103,13 @@ func init() { } func runClean(cmd *base.Command, args []string) { - for _, pkg := range load.PackagesAndErrors(args) { - clean(pkg) + if len(args) == 0 && modload.Failed() { + // Don't try to clean current directory, + // which will cause modload to base.Fatalf. + } else { + for _, pkg := range load.PackagesAndErrors(args) { + clean(pkg) + } } if cleanCache { @@ -138,6 +151,29 @@ func runClean(cmd *base.Command, args []string) { } } } + + if cleanModcache { + if modfetch.PkgMod == "" { + base.Fatalf("go clean -modcache: no module cache") + } + if err := removeAll(modfetch.PkgMod); err != nil { + base.Errorf("go clean -modcache: %v", err) + } + } +} + +func removeAll(dir string) error { + // Module cache has 0555 directories; make them writable in order to remove content. + filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return nil // ignore errors walking in file system + } + if info.IsDir() { + os.Chmod(path, 0777) + } + return nil + }) + return os.RemoveAll(dir) } var cleaned = map[*load.Package]bool{} diff --git a/libgo/go/cmd/go/internal/cmdflag/flag.go b/libgo/go/cmd/go/internal/cmdflag/flag.go index 7ab30221279..b2a67e6f74a 100644 --- a/libgo/go/cmd/go/internal/cmdflag/flag.go +++ b/libgo/go/cmd/go/internal/cmdflag/flag.go @@ -69,6 +69,14 @@ func SyntaxError(cmd, msg string) { os.Exit(2) } +// AddKnownFlags registers the flags in defns with base.AddKnownFlag. +func AddKnownFlags(cmd string, defns []*Defn) { + for _, f := range defns { + base.AddKnownFlag(f.Name) + base.AddKnownFlag(cmd + "." + f.Name) + } +} + // Parse sees if argument i is present in the definitions and if so, // returns its definition, value, and whether it consumed an extra word. // If the flag begins (cmd+".") it is ignored for the purpose of this function. @@ -121,3 +129,31 @@ func Parse(cmd string, defns []*Defn, args []string, i int) (f *Defn, value stri f = nil return } + +// FindGOFLAGS extracts and returns the flags matching defns from GOFLAGS. +// Ideally the caller would mention that the flags were from GOFLAGS +// when reporting errors, but that's too hard for now. +func FindGOFLAGS(defns []*Defn) []string { + var flags []string + for _, flag := range base.GOFLAGS() { + // Flags returned by base.GOFLAGS are well-formed, one of: + // -x + // --x + // -x=value + // --x=value + if strings.HasPrefix(flag, "--") { + flag = flag[1:] + } + name := flag[1:] + if i := strings.Index(name, "="); i >= 0 { + name = name[:i] + } + for _, f := range defns { + if name == f.Name { + flags = append(flags, flag) + break + } + } + } + return flags +} diff --git a/libgo/go/cmd/go/internal/dirhash/hash.go b/libgo/go/cmd/go/internal/dirhash/hash.go new file mode 100644 index 00000000000..61d8face567 --- /dev/null +++ b/libgo/go/cmd/go/internal/dirhash/hash.go @@ -0,0 +1,103 @@ +// 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 dirhash defines hashes over directory trees. +package dirhash + +import ( + "archive/zip" + "crypto/sha256" + "encoding/base64" + "errors" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" +) + +var DefaultHash = Hash1 + +type Hash func(files []string, open func(string) (io.ReadCloser, error)) (string, error) + +func Hash1(files []string, open func(string) (io.ReadCloser, error)) (string, error) { + h := sha256.New() + files = append([]string(nil), files...) + sort.Strings(files) + for _, file := range files { + if strings.Contains(file, "\n") { + return "", errors.New("filenames with newlines are not supported") + } + r, err := open(file) + if err != nil { + return "", err + } + hf := sha256.New() + _, err = io.Copy(hf, r) + r.Close() + if err != nil { + return "", err + } + fmt.Fprintf(h, "%x %s\n", hf.Sum(nil), file) + } + return "h1:" + base64.StdEncoding.EncodeToString(h.Sum(nil)), nil +} + +func HashDir(dir, prefix string, hash Hash) (string, error) { + files, err := DirFiles(dir, prefix) + if err != nil { + return "", err + } + osOpen := func(name string) (io.ReadCloser, error) { + return os.Open(filepath.Join(dir, strings.TrimPrefix(name, prefix))) + } + return hash(files, osOpen) +} + +func DirFiles(dir, prefix string) ([]string, error) { + var files []string + dir = filepath.Clean(dir) + err := filepath.Walk(dir, func(file string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return nil + } + rel := file + if dir != "." { + rel = file[len(dir)+1:] + } + f := filepath.Join(prefix, rel) + files = append(files, filepath.ToSlash(f)) + return nil + }) + if err != nil { + return nil, err + } + return files, nil +} + +func HashZip(zipfile string, hash Hash) (string, error) { + z, err := zip.OpenReader(zipfile) + if err != nil { + return "", err + } + defer z.Close() + var files []string + zfiles := make(map[string]*zip.File) + for _, file := range z.File { + files = append(files, file.Name) + zfiles[file.Name] = file + } + zipOpen := func(name string) (io.ReadCloser, error) { + f := zfiles[name] + if f == nil { + return nil, fmt.Errorf("file %q not found in zip", name) // should never happen + } + return f.Open() + } + return hash(files, zipOpen) +} diff --git a/libgo/go/cmd/go/internal/dirhash/hash_test.go b/libgo/go/cmd/go/internal/dirhash/hash_test.go new file mode 100644 index 00000000000..ed463c1949c --- /dev/null +++ b/libgo/go/cmd/go/internal/dirhash/hash_test.go @@ -0,0 +1,135 @@ +// 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 dirhash + +import ( + "archive/zip" + "crypto/sha256" + "encoding/base64" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "testing" +) + +func h(s string) string { + return fmt.Sprintf("%x", sha256.Sum256([]byte(s))) +} + +func htop(k string, s string) string { + sum := sha256.Sum256([]byte(s)) + return k + ":" + base64.StdEncoding.EncodeToString(sum[:]) +} + +func TestHash1(t *testing.T) { + files := []string{"xyz", "abc"} + open := func(name string) (io.ReadCloser, error) { + return ioutil.NopCloser(strings.NewReader("data for " + name)), nil + } + want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "abc", h("data for xyz"), "xyz")) + out, err := Hash1(files, open) + if err != nil { + t.Fatal(err) + } + if out != want { + t.Errorf("Hash1(...) = %s, want %s", out, want) + } + + _, err = Hash1([]string{"xyz", "a\nbc"}, open) + if err == nil { + t.Error("Hash1: expected error on newline in filenames") + } +} + +func TestHashDir(t *testing.T) { + dir, err := ioutil.TempDir("", "dirhash-test-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + if err := ioutil.WriteFile(filepath.Join(dir, "xyz"), []byte("data for xyz"), 0666); err != nil { + t.Fatal(err) + } + if err := ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("data for abc"), 0666); err != nil { + t.Fatal(err) + } + want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "prefix/abc", h("data for xyz"), "prefix/xyz")) + out, err := HashDir(dir, "prefix", Hash1) + if err != nil { + t.Fatalf("HashDir: %v", err) + } + if out != want { + t.Errorf("HashDir(...) = %s, want %s", out, want) + } +} + +func TestHashZip(t *testing.T) { + f, err := ioutil.TempFile("", "dirhash-test-") + if err != nil { + t.Fatal(err) + } + defer os.Remove(f.Name()) + defer f.Close() + + z := zip.NewWriter(f) + w, err := z.Create("prefix/xyz") + if err != nil { + t.Fatal(err) + } + w.Write([]byte("data for xyz")) + w, err = z.Create("prefix/abc") + if err != nil { + t.Fatal(err) + } + w.Write([]byte("data for abc")) + if err := z.Close(); err != nil { + t.Fatal(err) + } + if err := f.Close(); err != nil { + t.Fatal(err) + } + + want := htop("h1", fmt.Sprintf("%s %s\n%s %s\n", h("data for abc"), "prefix/abc", h("data for xyz"), "prefix/xyz")) + out, err := HashZip(f.Name(), Hash1) + if err != nil { + t.Fatalf("HashDir: %v", err) + } + if out != want { + t.Errorf("HashDir(...) = %s, want %s", out, want) + } +} + +func TestDirFiles(t *testing.T) { + dir, err := ioutil.TempDir("", "dirfiles-test-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + if err := ioutil.WriteFile(filepath.Join(dir, "xyz"), []byte("data for xyz"), 0666); err != nil { + t.Fatal(err) + } + if err := ioutil.WriteFile(filepath.Join(dir, "abc"), []byte("data for abc"), 0666); err != nil { + t.Fatal(err) + } + if err := os.Mkdir(filepath.Join(dir, "subdir"), 0777); err != nil { + t.Fatal(err) + } + if err := ioutil.WriteFile(filepath.Join(dir, "subdir", "xyz"), []byte("data for subdir xyz"), 0666); err != nil { + t.Fatal(err) + } + prefix := "foo/bar@v2.3.4" + out, err := DirFiles(dir, prefix) + if err != nil { + t.Fatalf("DirFiles: %v", err) + } + for _, file := range out { + if !strings.HasPrefix(file, prefix) { + t.Errorf("Dir file = %s, want prefix %s", file, prefix) + } + } +} diff --git a/libgo/go/cmd/go/internal/doc/doc.go b/libgo/go/cmd/go/internal/doc/doc.go index d73dd9ad914..4e7dca082d7 100644 --- a/libgo/go/cmd/go/internal/doc/doc.go +++ b/libgo/go/cmd/go/internal/doc/doc.go @@ -12,7 +12,7 @@ import ( var CmdDoc = &base.Command{ Run: runDoc, - UsageLine: "doc [-u] [-c] [package|[package.]symbol[.methodOrField]]", + UsageLine: "go doc [-u] [-c] [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 603f7b5060c..afadbade38e 100644 --- a/libgo/go/cmd/go/internal/envcmd/env.go +++ b/libgo/go/cmd/go/internal/envcmd/env.go @@ -9,6 +9,7 @@ import ( "encoding/json" "fmt" "os" + "path/filepath" "runtime" "strings" @@ -16,11 +17,12 @@ import ( "cmd/go/internal/cache" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/modload" "cmd/go/internal/work" ) var CmdEnv = &base.Command{ - UsageLine: "env [-json] [var ...]", + UsageLine: "go env [-json] [var ...]", Short: "print Go environment information", Long: ` Env prints Go environment information. @@ -52,17 +54,16 @@ func MkEnv() []cfg.EnvVar { {Name: "GOBIN", Value: cfg.GOBIN}, {Name: "GOCACHE", Value: cache.DefaultDir()}, {Name: "GOEXE", Value: cfg.ExeSuffix}, + {Name: "GOFLAGS", Value: os.Getenv("GOFLAGS")}, {Name: "GOHOSTARCH", Value: runtime.GOARCH}, {Name: "GOHOSTOS", Value: runtime.GOOS}, {Name: "GOOS", Value: cfg.Goos}, {Name: "GOPATH", Value: cfg.BuildContext.GOPATH}, + {Name: "GOPROXY", Value: os.Getenv("GOPROXY")}, {Name: "GORACE", Value: os.Getenv("GORACE")}, {Name: "GOROOT", Value: cfg.GOROOT}, {Name: "GOTMPDIR", Value: os.Getenv("GOTMPDIR")}, {Name: "GOTOOLDIR", Value: base.ToolDir}, - - // disable escape codes in clang errors - {Name: "TERM", Value: "dumb"}, } if work.GccgoBin != "" { @@ -78,6 +79,8 @@ func MkEnv() []cfg.EnvVar { env = append(env, cfg.EnvVar{Name: "GO386", Value: cfg.GO386}) case "mips", "mipsle": env = append(env, cfg.EnvVar{Name: "GOMIPS", Value: cfg.GOMIPS}) + case "mips64", "mips64le": + env = append(env, cfg.EnvVar{Name: "GOMIPS64", Value: cfg.GOMIPS64}) } cc := cfg.DefaultCC(cfg.Goos, cfg.Goarch) @@ -111,6 +114,18 @@ func findEnv(env []cfg.EnvVar, name string) string { // ExtraEnvVars returns environment variables that should not leak into child processes. func ExtraEnvVars() []cfg.EnvVar { + gomod := "" + if modload.Init(); modload.ModRoot != "" { + gomod = filepath.Join(modload.ModRoot, "go.mod") + } + return []cfg.EnvVar{ + {Name: "GOMOD", Value: gomod}, + } +} + +// ExtraEnvVarsCostly returns environment variables that should not leak into child processes +// but are costly to evaluate. +func ExtraEnvVarsCostly() []cfg.EnvVar { var b work.Builder b.Init() cppflags, cflags, cxxflags, fflags, ldflags, err := b.CFlags(&load.Package{}) @@ -120,6 +135,7 @@ func ExtraEnvVars() []cfg.EnvVar { return nil } cmd := b.GccCmd(".", "") + return []cfg.EnvVar{ // Note: Update the switch in runEnv below when adding to this list. {Name: "CGO_CFLAGS", Value: strings.Join(cflags, " ")}, @@ -134,13 +150,14 @@ func ExtraEnvVars() []cfg.EnvVar { func runEnv(cmd *base.Command, args []string) { env := cfg.CmdEnv + env = append(env, ExtraEnvVars()...) - // Do we need to call ExtraEnvVars, which is a bit expensive? + // Do we need to call ExtraEnvVarsCostly, which is a bit expensive? // Only if we're listing all environment variables ("go env") // or the variables being requested are in the extra list. - needExtra := true + needCostly := true if len(args) > 0 { - needExtra = false + needCostly = false for _, arg := range args { switch arg { case "CGO_CFLAGS", @@ -150,12 +167,12 @@ func runEnv(cmd *base.Command, args []string) { "CGO_LDFLAGS", "PKG_CONFIG", "GOGCCFLAGS": - needExtra = true + needCostly = true } } } - if needExtra { - env = append(env, ExtraEnvVars()...) + if needCostly { + env = append(env, ExtraEnvVarsCostly()...) } if len(args) > 0 { diff --git a/libgo/go/cmd/go/internal/fix/fix.go b/libgo/go/cmd/go/internal/fix/fix.go index 99c7ca51acf..aab164148ff 100644 --- a/libgo/go/cmd/go/internal/fix/fix.go +++ b/libgo/go/cmd/go/internal/fix/fix.go @@ -9,12 +9,15 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/modload" "cmd/go/internal/str" + "fmt" + "os" ) var CmdFix = &base.Command{ Run: runFix, - UsageLine: "fix [packages]", + UsageLine: "go fix [packages]", Short: "update packages to use new APIs", Long: ` Fix runs the Go fix command on the packages named by the import paths. @@ -29,7 +32,15 @@ See also: go fmt, go vet. } func runFix(cmd *base.Command, args []string) { + printed := false for _, pkg := range load.Packages(args) { + if modload.Enabled() && !pkg.Module.Main { + if !printed { + fmt.Fprintf(os.Stderr, "go: not fixing packages in dependency modules\n") + printed = true + } + continue + } // Use pkg.gofiles instead of pkg.Dir so that // the command only applies to this package, // not to packages in subdirectories. diff --git a/libgo/go/cmd/go/internal/fmtcmd/fmt.go b/libgo/go/cmd/go/internal/fmtcmd/fmt.go index eb96823fa6a..8e4ef372816 100644 --- a/libgo/go/cmd/go/internal/fmtcmd/fmt.go +++ b/libgo/go/cmd/go/internal/fmtcmd/fmt.go @@ -6,6 +6,7 @@ package fmtcmd import ( + "fmt" "os" "path/filepath" "runtime" @@ -15,6 +16,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/modload" "cmd/go/internal/str" ) @@ -24,7 +26,7 @@ func init() { var CmdFmt = &base.Command{ Run: runFmt, - UsageLine: "fmt [-n] [-x] [packages]", + UsageLine: "go fmt [-n] [-x] [packages]", Short: "gofmt (reformat) package sources", Long: ` Fmt runs the command 'gofmt -l -w' on the packages named @@ -43,6 +45,7 @@ See also: go fix, go vet. } func runFmt(cmd *base.Command, args []string) { + printed := false gofmt := gofmtPath() procs := runtime.GOMAXPROCS(0) var wg sync.WaitGroup @@ -57,6 +60,13 @@ func runFmt(cmd *base.Command, args []string) { }() } for _, pkg := range load.PackagesAndErrors(args) { + if modload.Enabled() && pkg.Module != nil && !pkg.Module.Main { + if !printed { + fmt.Fprintf(os.Stderr, "go: not formatting packages in dependency modules\n") + printed = true + } + continue + } if pkg.Error != nil { if strings.HasPrefix(pkg.Error.Err, "build constraints exclude all Go files") { // Skip this error, as we will format diff --git a/libgo/go/cmd/go/internal/generate/generate.go b/libgo/go/cmd/go/internal/generate/generate.go index 75c0d3b09d6..9482be98aef 100644 --- a/libgo/go/cmd/go/internal/generate/generate.go +++ b/libgo/go/cmd/go/internal/generate/generate.go @@ -21,12 +21,13 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/modload" "cmd/go/internal/work" ) var CmdGenerate = &base.Command{ Run: runGenerate, - UsageLine: "generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]", + UsageLine: "go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]", Short: "generate Go files by processing source", Long: ` Generate runs commands described by directives within existing @@ -47,6 +48,12 @@ that can be run locally. It must either be in the shell path (gofmt), a fully qualified path (/usr/you/bin/mytool), or a command alias, described below. +To convey to humans and machine tools that code is generated, +generated source should have a line early in the file that +matches the following regular expression (in Go syntax): + + ^// Code generated .* DO NOT EDIT\.$ + Note that go generate does not parse the file, so lines that look like directives in comments or multiline strings will be treated as directives. @@ -152,9 +159,28 @@ func runGenerate(cmd *base.Command, args []string) { } } // Even if the arguments are .go files, this loop suffices. + printed := false for _, pkg := range load.Packages(args) { + if modload.Enabled() && !pkg.Module.Main { + if !printed { + fmt.Fprintf(os.Stderr, "go: not generating in packages in dependency modules\n") + printed = true + } + continue + } + + pkgName := pkg.Name + for _, file := range pkg.InternalGoFiles() { - if !generate(pkg.Name, file) { + if !generate(pkgName, file) { + break + } + } + + pkgName += "_test" + + for _, file := range pkg.InternalXGoFiles() { + if !generate(pkgName, file) { break } } diff --git a/libgo/go/cmd/go/internal/get/discovery.go b/libgo/go/cmd/go/internal/get/discovery.go index 97aa1d7e8d6..6ba5c091e39 100644 --- a/libgo/go/cmd/go/internal/get/discovery.go +++ b/libgo/go/cmd/go/internal/get/discovery.go @@ -28,7 +28,7 @@ func charsetReader(charset string, input io.Reader) (io.Reader, error) { // parseMetaGoImports returns meta imports from the HTML in r. // Parsing ends at the end of the section or the beginning of the . -func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) { +func parseMetaGoImports(r io.Reader, mod ModuleMode) (imports []metaImport, err error) { d := xml.NewDecoder(r) d.CharsetReader = charsetReader d.Strict = false @@ -39,13 +39,13 @@ func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) { if err == io.EOF || len(imports) > 0 { err = nil } - return + break } if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") { - return + break } if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") { - return + break } e, ok := t.(xml.StartElement) if !ok || !strings.EqualFold(e.Name.Local, "meta") { @@ -55,13 +55,6 @@ func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) { continue } if f := strings.Fields(attrValue(e.Attr, "content")); len(f) == 3 { - // Ignore VCS type "mod", which is new Go modules. - // This code is for old go get and must ignore the new mod lines. - // Otherwise matchGoImport will complain about two - // different metaImport lines for the same Prefix. - if f[1] == "mod" { - continue - } imports = append(imports, metaImport{ Prefix: f[0], VCS: f[1], @@ -69,6 +62,27 @@ func parseMetaGoImports(r io.Reader) (imports []metaImport, err error) { }) } } + + // Extract mod entries if we are paying attention to them. + var list []metaImport + var have map[string]bool + if mod == PreferMod { + have = make(map[string]bool) + for _, m := range imports { + if m.VCS == "mod" { + have[m.Prefix] = true + list = append(list, m) + } + } + } + + // Append non-mod entries, ignoring those superseded by a mod entry. + for _, m := range imports { + if m.VCS != "mod" && !have[m.Prefix] { + list = append(list, m) + } + } + return list, nil } // attrValue returns the attribute value for the case-insensitive key diff --git a/libgo/go/cmd/go/internal/get/get.go b/libgo/go/cmd/go/internal/get/get.go index 5bfeac387cc..e4148bceb04 100644 --- a/libgo/go/cmd/go/internal/get/get.go +++ b/libgo/go/cmd/go/internal/get/get.go @@ -16,13 +16,14 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/search" "cmd/go/internal/str" "cmd/go/internal/web" "cmd/go/internal/work" ) var CmdGet = &base.Command{ - UsageLine: "get [-d] [-f] [-fix] [-insecure] [-t] [-u] [-v] [build flags] [packages]", + UsageLine: "go get [-d] [-f] [-t] [-u] [-v] [-fix] [-insecure] [build flags] [packages]", Short: "download and install packages and dependencies", Long: ` Get downloads the packages named by the import paths, along with their @@ -73,23 +74,56 @@ For more about specifying packages, see 'go help packages'. For more about how 'go get' finds source code to download, see 'go help importpath'. +This text describes the behavior of get when using GOPATH +to manage source code and dependencies. +If instead the go command is running in module-aware mode, +the details of get's flags and effects change, as does 'go help get'. +See 'go help modules' and 'go help module-get'. + See also: go build, go install, go clean. `, } -var getD = CmdGet.Flag.Bool("d", false, "") -var getF = CmdGet.Flag.Bool("f", false, "") -var getT = CmdGet.Flag.Bool("t", false, "") -var getU = CmdGet.Flag.Bool("u", false, "") -var getFix = CmdGet.Flag.Bool("fix", false, "") -var getInsecure = CmdGet.Flag.Bool("insecure", false, "") +var HelpGopathGet = &base.Command{ + UsageLine: "gopath-get", + Short: "legacy GOPATH go get", + Long: ` +The 'go get' command changes behavior depending on whether the +go command is running in module-aware mode or legacy GOPATH mode. +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: ` + CmdGet.UsageLine + ` +` + CmdGet.Long, +} + +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, "") + + Insecure bool +) func init() { work.AddBuildFlags(CmdGet) CmdGet.Run = runGet // break init loop + CmdGet.Flag.BoolVar(&Insecure, "insecure", Insecure, "") } func runGet(cmd *base.Command, args []string) { + if cfg.ModulesEnabled { + // Should not happen: main.go should install the separate module-enabled get code. + base.Fatalf("go get: modules not implemented") + } + if cfg.GoModInGOPATH != "" { + // Warn about not using modules with GO111MODULE=auto when go.mod exists. + // To silence the warning, users can set GO111MODULE=off. + fmt.Fprintf(os.Stderr, "go get: warning: modules disabled by GO111MODULE=auto in GOPATH/src;\n\tignoring %s;\n\tsee 'go help modules'\n", base.ShortPath(cfg.GoModInGOPATH)) + } + work.BuildInit() if *getF && !*getU { @@ -129,9 +163,8 @@ func runGet(cmd *base.Command, args []string) { if *getT { mode |= load.GetTestDeps } - args = downloadPaths(args) - for _, arg := range args { - download(arg, nil, &stk, mode) + for _, pkg := range downloadPaths(args) { + download(pkg, nil, &stk, mode) } base.ExitIfErrors() @@ -150,8 +183,7 @@ func runGet(cmd *base.Command, args []string) { // This leads to duplicated loads of the standard packages. load.ClearCmdCache() - args = load.ImportPaths(args) - load.PackagesForBuild(args) + pkgs := load.PackagesForBuild(args) // Phase 3. Install. if *getD { @@ -161,7 +193,7 @@ func runGet(cmd *base.Command, args []string) { return } - work.InstallPackages(args, true) + work.InstallPackages(args, pkgs) } // downloadPaths prepares the list of paths to pass to download. @@ -169,28 +201,21 @@ func runGet(cmd *base.Command, args []string) { // for a particular pattern, downloadPaths leaves it in the result list, // in the hope that we can figure out the repository from the // initial ...-free prefix. -func downloadPaths(args []string) []string { - args = load.ImportPathsNoDotExpansion(args) - var out []string - for _, a := range args { - if strings.Contains(a, "...") { - var expand []string - // Use matchPackagesInFS to avoid printing - // warnings. They will be printed by the - // eventual call to importPaths instead. - if build.IsLocalImport(a) { - expand = load.MatchPackagesInFS(a) - } else { - expand = load.MatchPackages(a) - } - if len(expand) > 0 { - out = append(out, expand...) - continue - } +func downloadPaths(patterns []string) []string { + for _, arg := range patterns { + if strings.Contains(arg, "@") { + base.Fatalf("go: cannot use path@version syntax in GOPATH mode") } - out = append(out, a) } - return out + var pkgs []string + for _, m := range search.ImportPathsQuiet(patterns) { + if len(m.Pkgs) == 0 && strings.Contains(m.Pattern, "...") { + pkgs = append(pkgs, m.Pattern) + } else { + pkgs = append(pkgs, m.Pkgs...) + } + } + return pkgs } // downloadCache records the import paths we have already @@ -215,7 +240,7 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) } load1 := func(path string, mode int) *load.Package { if parent == nil { - return load.LoadPackage(path, stk) + return load.LoadPackageNoFlags(path, stk) } return load.LoadImport(path, parent.Dir, parent, stk, nil, mode|load.ResolveModule) } @@ -271,9 +296,9 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) // for p has been replaced in the package cache. if wildcardOkay && strings.Contains(arg, "...") { if build.IsLocalImport(arg) { - args = load.MatchPackagesInFS(arg) + args = search.MatchPackagesInFS(arg).Pkgs } else { - args = load.MatchPackages(arg) + args = search.MatchPackages(arg).Pkgs } isWildcard = true } @@ -304,7 +329,7 @@ func download(arg string, parent *load.Package, stk *load.ImportStack, mode int) base.Run(cfg.BuildToolexec, str.StringList(base.Tool("fix"), files)) // The imports might have changed, so reload again. - p = load.ReloadPackage(arg, stk) + p = load.ReloadPackageNoFlags(arg, stk) if p.Error != nil { base.Errorf("%s", p.Error) return @@ -369,10 +394,11 @@ func downloadPackage(p *load.Package) error { vcs *vcsCmd repo, rootPath string err error + blindRepo bool // set if the repo has unusual configuration ) security := web.Secure - if *getInsecure { + if Insecure { security = web.Insecure } @@ -389,20 +415,22 @@ func downloadPackage(p *load.Package) error { dir := filepath.Join(p.Internal.Build.SrcRoot, filepath.FromSlash(rootPath)) remote, err := vcs.remoteRepo(vcs, dir) if err != nil { - return err + // Proceed anyway. The package is present; we likely just don't understand + // the repo configuration (e.g. unusual remote protocol). + blindRepo = true } repo = remote - if !*getF { - if rr, err := repoRootForImportPath(p.ImportPath, security); err == nil { - repo := rr.repo + if !*getF && err == nil { + if rr, err := RepoRootForImportPath(p.ImportPath, IgnoreMod, security); err == nil { + repo := rr.Repo if rr.vcs.resolveRepo != nil { resolved, err := rr.vcs.resolveRepo(rr.vcs, dir, repo) if err == nil { repo = resolved } } - if remote != repo && rr.isCustom { - return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote) + if remote != repo && rr.IsCustom { + return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.Root, repo, dir, remote) } } } @@ -410,13 +438,13 @@ func downloadPackage(p *load.Package) error { } else { // Analyze the import path to determine the version control system, // repository, and the import path for the root of the repository. - rr, err := repoRootForImportPath(p.ImportPath, security) + rr, err := RepoRootForImportPath(p.ImportPath, IgnoreMod, security) if err != nil { return err } - vcs, repo, rootPath = rr.vcs, rr.repo, rr.root + vcs, repo, rootPath = rr.vcs, rr.Repo, rr.Root } - if !vcs.isSecure(repo) && !*getInsecure { + if !blindRepo && !vcs.isSecure(repo) && !Insecure { return fmt.Errorf("cannot download, %v uses insecure protocol", repo) } diff --git a/libgo/go/cmd/go/internal/get/pkg_test.go b/libgo/go/cmd/go/internal/get/pkg_test.go index 1179d86693a..fc6a179c2e1 100644 --- a/libgo/go/cmd/go/internal/get/pkg_test.go +++ b/libgo/go/cmd/go/internal/get/pkg_test.go @@ -33,15 +33,18 @@ func TestFoldDup(t *testing.T) { var parseMetaGoImportsTests = []struct { in string + mod ModuleMode out []metaImport }{ { ``, + IgnoreMod, []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}}, }, { ` `, + IgnoreMod, []metaImport{ {"foo/bar", "git", "https://github.com/rsc/foo/bar"}, {"baz/quux", "git", "http://github.com/rsc/baz/quux"}, @@ -50,6 +53,7 @@ var parseMetaGoImportsTests = []struct { { ` `, + IgnoreMod, []metaImport{ {"foo/bar", "git", "https://github.com/rsc/foo/bar"}, }, @@ -57,35 +61,65 @@ var parseMetaGoImportsTests = []struct { { ` `, + IgnoreMod, []metaImport{ {"foo/bar", "git", "https://github.com/rsc/foo/bar"}, }, }, + { + ` + `, + PreferMod, + []metaImport{ + {"foo/bar", "mod", "http://github.com/rsc/baz/quux"}, + }, + }, { ` `, + IgnoreMod, []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}}, }, { ` `, + IgnoreMod, []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}}, }, { ``, + IgnoreMod, []metaImport{{"foo/bar", "git", "https://github.com/rsc/foo/bar"}}, }, { // XML doesn't like
. `Page Not Found
DRAFT
`, + IgnoreMod, []metaImport{{"chitin.io/chitin", "git", "https://github.com/chitin-io/chitin"}}, }, + { + ` + + `, + IgnoreMod, + []metaImport{{"myitcv.io", "git", "https://github.com/myitcv/x"}}, + }, + { + ` + + `, + PreferMod, + []metaImport{ + {"myitcv.io/blah2", "mod", "https://raw.githubusercontent.com/myitcv/pubx/master"}, + {"myitcv.io", "git", "https://github.com/myitcv/x"}, + }, + }, } func TestParseMetaGoImports(t *testing.T) { for i, tt := range parseMetaGoImportsTests { - out, err := parseMetaGoImports(strings.NewReader(tt.in)) + out, err := parseMetaGoImports(strings.NewReader(tt.in), tt.mod) if err != nil { t.Errorf("test#%d: %v", i, err) continue diff --git a/libgo/go/cmd/go/internal/get/vcs.go b/libgo/go/cmd/go/internal/get/vcs.go index 0b2a04e04f8..5cd164f2ff3 100644 --- a/libgo/go/cmd/go/internal/get/vcs.go +++ b/libgo/go/cmd/go/internal/get/vcs.go @@ -5,7 +5,6 @@ package get import ( - "bytes" "encoding/json" "errors" "fmt" @@ -428,19 +427,18 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool) fmt.Printf("cd %s\n", dir) fmt.Printf("%s %s\n", v.cmd, strings.Join(args, " ")) } - var buf bytes.Buffer - cmd.Stdout = &buf - cmd.Stderr = &buf - err = cmd.Run() - out := buf.Bytes() + out, err := cmd.Output() if err != nil { if verbose || cfg.BuildV { fmt.Fprintf(os.Stderr, "# cd %s; %s %s\n", dir, v.cmd, strings.Join(args, " ")) - os.Stderr.Write(out) + if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 { + os.Stderr.Write(ee.Stderr) + } else { + fmt.Fprintf(os.Stderr, err.Error()) + } } - return out, err } - return out, nil + return out, err } // ping pings to determine scheme to use. @@ -624,27 +622,29 @@ func checkNestedVCS(vcs *vcsCmd, dir, srcRoot string) error { return nil } -// repoRoot represents a version control system, a repo, and a root of -// where to put it on disk. -type repoRoot struct { - vcs *vcsCmd +// RepoRoot describes the repository root for a tree of source code. +type RepoRoot struct { + Repo string // repository URL, including scheme + Root string // import path corresponding to root of repo + IsCustom bool // defined by served tags (as opposed to hard-coded pattern) + VCS string // vcs type ("mod", "git", ...) - // repo is the repository URL, including scheme - repo string - - // root is the import path corresponding to the root of the - // repository - root string - - // isCustom is true for custom import paths (those defined by HTML meta tags) - isCustom bool + vcs *vcsCmd // internal: vcs command access } var httpPrefixRE = regexp.MustCompile(`^https?:`) -// repoRootForImportPath analyzes importPath to determine the +// ModuleMode specifies whether to prefer modules when looking up code sources. +type ModuleMode int + +const ( + IgnoreMod ModuleMode = iota + PreferMod +) + +// RepoRootForImportPath analyzes importPath to determine the // version control system, and code repository to use. -func repoRootForImportPath(importPath string, security web.SecurityMode) (*repoRoot, error) { +func RepoRootForImportPath(importPath string, mod ModuleMode, security web.SecurityMode) (*RepoRoot, error) { rr, err := repoRootFromVCSPaths(importPath, "", security, vcsPaths) if err == errUnknownSite { // If there are wildcards, look up the thing before the wildcard, @@ -654,7 +654,7 @@ func repoRootForImportPath(importPath string, security web.SecurityMode) (*repoR if i := strings.Index(lookup, "/.../"); i >= 0 { lookup = lookup[:i] } - rr, err = repoRootForImportDynamic(lookup, security) + rr, err = repoRootForImportDynamic(lookup, mod, security) if err != nil { err = fmt.Errorf("unrecognized import path %q (%v)", importPath, err) } @@ -667,7 +667,7 @@ func repoRootForImportPath(importPath string, security web.SecurityMode) (*repoR } } - if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.root, "...") { + if err == nil && strings.Contains(importPath, "...") && strings.Contains(rr.Root, "...") { // Do not allow wildcards in the repo root. rr = nil err = fmt.Errorf("cannot expand ... in %q", importPath) @@ -680,7 +680,7 @@ var errUnknownSite = errors.New("dynamic lookup required to find mapping") // repoRootFromVCSPaths attempts to map importPath to a repoRoot // using the mappings defined in vcsPaths. // If scheme is non-empty, that scheme is forced. -func repoRootFromVCSPaths(importPath, scheme string, security web.SecurityMode, vcsPaths []*vcsPath) (*repoRoot, error) { +func repoRootFromVCSPaths(importPath, scheme string, security web.SecurityMode, vcsPaths []*vcsPath) (*RepoRoot, error) { // A common error is to use https://packagepath because that's what // hg and git require. Diagnose this helpfully. if loc := httpPrefixRE.FindStringIndex(importPath); loc != nil { @@ -733,28 +733,32 @@ func repoRootFromVCSPaths(importPath, scheme string, security web.SecurityMode, if security == web.Secure && !vcs.isSecureScheme(scheme) { continue } - if vcs.ping(scheme, match["repo"]) == nil { + if vcs.pingCmd != "" && vcs.ping(scheme, match["repo"]) == nil { match["repo"] = scheme + "://" + match["repo"] - break + goto Found } } + // No scheme found. Fall back to the first one. + match["repo"] = vcs.scheme[0] + "://" + match["repo"] + Found: } } - rr := &repoRoot{ + rr := &RepoRoot{ + Repo: match["repo"], + Root: match["root"], + VCS: vcs.cmd, vcs: vcs, - repo: match["repo"], - root: match["root"], } return rr, nil } return nil, errUnknownSite } -// repoRootForImportDynamic finds a *repoRoot for a custom domain that's not +// repoRootForImportDynamic finds a *RepoRoot for a custom domain that's not // statically known by repoRootForImportPathStatic. // // This handles custom import paths like "name.tld/pkg/foo" or just "name.tld". -func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*repoRoot, error) { +func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.SecurityMode) (*RepoRoot, error) { slash := strings.Index(importPath, "/") if slash < 0 { slash = len(importPath) @@ -772,7 +776,7 @@ func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*re return nil, fmt.Errorf(msg, err) } defer body.Close() - imports, err := parseMetaGoImports(body) + imports, err := parseMetaGoImports(body, mod) if err != nil { return nil, fmt.Errorf("parsing %s: %v", importPath, err) } @@ -799,7 +803,7 @@ func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*re } urlStr0 := urlStr var imports []metaImport - urlStr, imports, err = metaImportsForPrefix(mmi.Prefix, security) + urlStr, imports, err = metaImportsForPrefix(mmi.Prefix, mod, security) if err != nil { return nil, err } @@ -809,48 +813,34 @@ func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*re } } - if err := validateRepoRootScheme(mmi.RepoRoot); err != nil { + if err := validateRepoRoot(mmi.RepoRoot); err != nil { return nil, fmt.Errorf("%s: invalid repo root %q: %v", urlStr, mmi.RepoRoot, err) } - rr := &repoRoot{ - vcs: vcsByCmd(mmi.VCS), - repo: mmi.RepoRoot, - root: mmi.Prefix, - isCustom: true, - } - if rr.vcs == nil { + vcs := vcsByCmd(mmi.VCS) + if vcs == nil && mmi.VCS != "mod" { return nil, fmt.Errorf("%s: unknown vcs %q", urlStr, mmi.VCS) } + + rr := &RepoRoot{ + Repo: mmi.RepoRoot, + Root: mmi.Prefix, + IsCustom: true, + VCS: mmi.VCS, + vcs: vcs, + } return rr, nil } -// validateRepoRootScheme returns an error if repoRoot does not seem -// to have a valid URL scheme. At this point we permit things that -// aren't valid URLs, although later, if not using -insecure, we will -// restrict repoRoots to be valid URLs. This is only because we've -// historically permitted them, and people may depend on that. -func validateRepoRootScheme(repoRoot string) error { - end := strings.Index(repoRoot, "://") - if end <= 0 { +// validateRepoRoot returns an error if repoRoot does not seem to be +// a valid URL with scheme. +func validateRepoRoot(repoRoot string) error { + url, err := url.Parse(repoRoot) + if err != nil { + return err + } + if url.Scheme == "" { return errors.New("no scheme") } - - // RFC 3986 section 3.1. - for i := 0; i < end; i++ { - c := repoRoot[i] - switch { - case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z': - // OK. - case '0' <= c && c <= '9' || c == '+' || c == '-' || c == '.': - // OK except at start. - if i == 0 { - return errors.New("invalid scheme") - } - default: - return errors.New("invalid scheme") - } - } - return nil } @@ -868,7 +858,7 @@ var ( // It is an error if no imports are found. // urlStr will still be valid if err != nil. // The returned urlStr will be of the form "https://golang.org/x/tools?go-get=1" -func metaImportsForPrefix(importPrefix string, security web.SecurityMode) (urlStr string, imports []metaImport, err error) { +func metaImportsForPrefix(importPrefix string, mod ModuleMode, security web.SecurityMode) (urlStr string, imports []metaImport, err error) { setCache := func(res fetchResult) (fetchResult, error) { fetchCacheMu.Lock() defer fetchCacheMu.Unlock() @@ -888,7 +878,7 @@ func metaImportsForPrefix(importPrefix string, security web.SecurityMode) (urlSt if err != nil { return setCache(fetchResult{urlStr: urlStr, err: fmt.Errorf("fetch %s: %v", urlStr, err)}) } - imports, err := parseMetaGoImports(body) + imports, err := parseMetaGoImports(body, mod) if err != nil { return setCache(fetchResult{urlStr: urlStr, err: fmt.Errorf("parsing %s: %v", urlStr, err)}) } @@ -956,7 +946,13 @@ func matchGoImport(imports []metaImport, importPath string) (metaImport, error) continue } - if match != -1 { + if match >= 0 { + if imports[match].VCS == "mod" && im.VCS != "mod" { + // All the mod entries precede all the non-mod entries. + // We have a mod entry and don't care about the rest, + // matching or not. + break + } return metaImport{}, fmt.Errorf("multiple meta tags match import path %q", importPath) } match = i @@ -1001,7 +997,7 @@ var vcsPaths = []*vcsPath{ // IBM DevOps Services (JazzHub) { prefix: "hub.jazz.net/git/", - re: `^(?Phub.jazz.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`, + re: `^(?Phub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`, vcs: "git", repo: "https://{root}", check: noVCSSuffix, @@ -1010,7 +1006,7 @@ var vcsPaths = []*vcsPath{ // Git at Apache { prefix: "git.apache.org/", - re: `^(?Pgit.apache.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`, + re: `^(?Pgit\.apache\.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`, vcs: "git", repo: "https://{root}", }, diff --git a/libgo/go/cmd/go/internal/get/vcs_test.go b/libgo/go/cmd/go/internal/get/vcs_test.go index a6f8642026c..d13721bed1a 100644 --- a/libgo/go/cmd/go/internal/get/vcs_test.go +++ b/libgo/go/cmd/go/internal/get/vcs_test.go @@ -16,49 +16,53 @@ import ( "cmd/go/internal/web" ) -// Test that RepoRootForImportPath creates the correct RepoRoot for a given importPath. +// Test that RepoRootForImportPath determines the correct RepoRoot for a given importPath. // TODO(cmang): Add tests for SVN and BZR. func TestRepoRootForImportPath(t *testing.T) { testenv.MustHaveExternalNetwork(t) tests := []struct { path string - want *repoRoot + want *RepoRoot }{ { "github.com/golang/groupcache", - &repoRoot{ + &RepoRoot{ vcs: vcsGit, - repo: "https://github.com/golang/groupcache", + Repo: "https://github.com/golang/groupcache", }, }, // Unicode letters in directories (issue 18660). { "github.com/user/unicode/испытание", - &repoRoot{ + &RepoRoot{ vcs: vcsGit, - repo: "https://github.com/user/unicode", + Repo: "https://github.com/user/unicode", }, }, // IBM DevOps Services tests { "hub.jazz.net/git/user1/pkgname", - &repoRoot{ + &RepoRoot{ vcs: vcsGit, - repo: "https://hub.jazz.net/git/user1/pkgname", + Repo: "https://hub.jazz.net/git/user1/pkgname", }, }, { "hub.jazz.net/git/user1/pkgname/submodule/submodule/submodule", - &repoRoot{ + &RepoRoot{ vcs: vcsGit, - repo: "https://hub.jazz.net/git/user1/pkgname", + Repo: "https://hub.jazz.net/git/user1/pkgname", }, }, { "hub.jazz.net", nil, }, + { + "hubajazz.net", + nil, + }, { "hub2.jazz.net", nil, @@ -87,9 +91,9 @@ func TestRepoRootForImportPath(t *testing.T) { }, { "hub.jazz.net/git/user/pkg.name", - &repoRoot{ + &RepoRoot{ vcs: vcsGit, - repo: "https://hub.jazz.net/git/user/pkg.name", + Repo: "https://hub.jazz.net/git/user/pkg.name", }, }, // User names cannot have uppercase letters @@ -100,9 +104,9 @@ func TestRepoRootForImportPath(t *testing.T) { // OpenStack tests { "git.openstack.org/openstack/swift", - &repoRoot{ + &RepoRoot{ vcs: vcsGit, - repo: "https://git.openstack.org/openstack/swift", + Repo: "https://git.openstack.org/openstack/swift", }, }, // Trailing .git is less preferred but included for @@ -110,16 +114,16 @@ func TestRepoRootForImportPath(t *testing.T) { // be compilable on both old and new go { "git.openstack.org/openstack/swift.git", - &repoRoot{ + &RepoRoot{ vcs: vcsGit, - repo: "https://git.openstack.org/openstack/swift.git", + Repo: "https://git.openstack.org/openstack/swift.git", }, }, { "git.openstack.org/openstack/swift/go/hummingbird", - &repoRoot{ + &RepoRoot{ vcs: vcsGit, - repo: "https://git.openstack.org/openstack/swift", + Repo: "https://git.openstack.org/openstack/swift", }, }, { @@ -140,25 +144,29 @@ func TestRepoRootForImportPath(t *testing.T) { "git.apache.org/package-name/path/to/lib", nil, }, + { + "gitbapache.org", + nil, + }, { "git.apache.org/package-name.git", - &repoRoot{ + &RepoRoot{ vcs: vcsGit, - repo: "https://git.apache.org/package-name.git", + Repo: "https://git.apache.org/package-name.git", }, }, { "git.apache.org/package-name_2.x.git/path/to/lib", - &repoRoot{ + &RepoRoot{ vcs: vcsGit, - repo: "https://git.apache.org/package-name_2.x.git", + Repo: "https://git.apache.org/package-name_2.x.git", }, }, { "chiselapp.com/user/kyle/repository/fossilgg", - &repoRoot{ + &RepoRoot{ vcs: vcsFossil, - repo: "https://chiselapp.com/user/kyle/repository/fossilgg", + Repo: "https://chiselapp.com/user/kyle/repository/fossilgg", }, }, { @@ -173,21 +181,21 @@ func TestRepoRootForImportPath(t *testing.T) { } for _, test := range tests { - got, err := repoRootForImportPath(test.path, web.Secure) + got, err := RepoRootForImportPath(test.path, IgnoreMod, web.Secure) want := test.want if want == nil { if err == nil { - t.Errorf("repoRootForImportPath(%q): Error expected but not received", test.path) + t.Errorf("RepoRootForImportPath(%q): Error expected but not received", test.path) } continue } if err != nil { - t.Errorf("repoRootForImportPath(%q): %v", test.path, err) + t.Errorf("RepoRootForImportPath(%q): %v", test.path, err) continue } - if got.vcs.name != want.vcs.name || got.repo != want.repo { - t.Errorf("repoRootForImportPath(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.vcs, got.repo, want.vcs, want.repo) + if got.vcs.name != want.vcs.name || got.Repo != want.Repo { + t.Errorf("RepoRootForImportPath(%q) = VCS(%s) Repo(%s), want VCS(%s) Repo(%s)", test.path, got.vcs, got.Repo, want.vcs, want.Repo) } } } @@ -219,18 +227,18 @@ func TestFromDir(t *testing.T) { f.Close() } - want := repoRoot{ + want := RepoRoot{ vcs: vcs, - root: path.Join("example.com", vcs.name), + Root: path.Join("example.com", vcs.name), } - var got repoRoot - got.vcs, got.root, err = vcsFromDir(dir, tempDir) + var got RepoRoot + got.vcs, got.Root, err = vcsFromDir(dir, tempDir) if err != nil { t.Errorf("FromDir(%q, %q): %v", dir, tempDir, err) continue } - if got.vcs.name != want.vcs.name || got.root != want.root { - t.Errorf("FromDir(%q, %q) = VCS(%s) Root(%s), want VCS(%s) Root(%s)", dir, tempDir, got.vcs, got.root, want.vcs, want.root) + if got.vcs.name != want.vcs.name || got.Root != want.Root { + t.Errorf("FromDir(%q, %q) = VCS(%s) Root(%s), want VCS(%s) Root(%s)", dir, tempDir, got.vcs, got.Root, want.vcs, want.Root) } } } @@ -393,6 +401,22 @@ func TestMatchGoImport(t *testing.T) { path: "different.example.com/user/foo", err: errors.New("meta tags do not match import path"), }, + { + imports: []metaImport{ + {Prefix: "myitcv.io/blah2", VCS: "mod", RepoRoot: "https://raw.githubusercontent.com/myitcv/pubx/master"}, + {Prefix: "myitcv.io", VCS: "git", RepoRoot: "https://github.com/myitcv/x"}, + }, + path: "myitcv.io/blah2/foo", + mi: metaImport{Prefix: "myitcv.io/blah2", VCS: "mod", RepoRoot: "https://raw.githubusercontent.com/myitcv/pubx/master"}, + }, + { + imports: []metaImport{ + {Prefix: "myitcv.io/blah2", VCS: "mod", RepoRoot: "https://raw.githubusercontent.com/myitcv/pubx/master"}, + {Prefix: "myitcv.io", VCS: "git", RepoRoot: "https://github.com/myitcv/x"}, + }, + path: "myitcv.io/other", + mi: metaImport{Prefix: "myitcv.io", VCS: "git", RepoRoot: "https://github.com/myitcv/x"}, + }, } for _, test := range tests { @@ -409,45 +433,46 @@ func TestMatchGoImport(t *testing.T) { } } -func TestValidateRepoRootScheme(t *testing.T) { +func TestValidateRepoRoot(t *testing.T) { tests := []struct { root string - err string + ok bool }{ { root: "", - err: "no scheme", + ok: false, }, { root: "http://", - err: "", + ok: true, }, { - root: "a://", - err: "", + root: "git+ssh://", + ok: true, }, { - root: "a#://", - err: "invalid scheme", + root: "http#://", + ok: false, + }, + { + root: "-config", + ok: false, }, { root: "-config://", - err: "invalid scheme", + ok: false, }, } for _, test := range tests { - err := validateRepoRootScheme(test.root) - if err == nil { - if test.err != "" { - t.Errorf("validateRepoRootScheme(%q) = nil, want %q", test.root, test.err) + err := validateRepoRoot(test.root) + ok := err == nil + if ok != test.ok { + want := "error" + if test.ok { + want = "nil" } - } else if test.err == "" { - if err != nil { - t.Errorf("validateRepoRootScheme(%q) = %q, want nil", test.root, test.err) - } - } else if err.Error() != test.err { - t.Errorf("validateRepoRootScheme(%q) = %q, want %q", test.root, err, test.err) + t.Errorf("validateRepoRoot(%q) = %q, want %s", test.root, err, want) } } } diff --git a/libgo/go/cmd/go/internal/help/help.go b/libgo/go/cmd/go/internal/help/help.go index b4c5217f836..a80afe36c41 100644 --- a/libgo/go/cmd/go/internal/help/help.go +++ b/libgo/go/cmd/go/internal/help/help.go @@ -21,82 +21,95 @@ import ( // Help implements the 'help' command. func Help(args []string) { - if len(args) == 0 { - PrintUsage(os.Stdout) - // not exit 2: succeeded at 'go help'. - return - } - if len(args) != 1 { - fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n") - os.Exit(2) // failed at 'go help' - } - - arg := args[0] - // 'go help documentation' generates doc.go. - if arg == "documentation" { + if len(args) == 1 && args[0] == "documentation" { fmt.Println("// Copyright 2011 The Go Authors. All rights reserved.") fmt.Println("// Use of this source code is governed by a BSD-style") fmt.Println("// license that can be found in the LICENSE file.") fmt.Println() - fmt.Println("// DO NOT EDIT THIS FILE. GENERATED BY mkalldocs.sh.") + fmt.Println("// Code generated by mkalldocs.sh; DO NOT EDIT.") fmt.Println("// Edit the documentation in other files and rerun mkalldocs.sh to generate this one.") fmt.Println() buf := new(bytes.Buffer) - PrintUsage(buf) + PrintUsage(buf, base.Go) usage := &base.Command{Long: buf.String()} - tmpl(&commentWriter{W: os.Stdout}, documentationTemplate, append([]*base.Command{usage}, base.Commands...)) + cmds := []*base.Command{usage} + for _, cmd := range base.Go.Commands { + if cmd.UsageLine == "gopath-get" { + // Avoid duplication of the "get" documentation. + continue + } + cmds = append(cmds, cmd) + cmds = append(cmds, cmd.Commands...) + } + tmpl(&commentWriter{W: os.Stdout}, documentationTemplate, cmds) fmt.Println("package main") return } - for _, cmd := range base.Commands { - if cmd.Name() == arg { - tmpl(os.Stdout, helpTemplate, cmd) - // not exit 2: succeeded at 'go help cmd'. - return + cmd := base.Go +Args: + for i, arg := range args { + for _, sub := range cmd.Commands { + if sub.Name() == arg { + cmd = sub + continue Args + } } + + // helpSuccess is the help command using as many args as possible that would succeed. + helpSuccess := "go help" + if i > 0 { + helpSuccess = " " + strings.Join(args[:i], " ") + } + fmt.Fprintf(os.Stderr, "go help %s: unknown help topic. Run '%s'.\n", strings.Join(args, " "), helpSuccess) + os.Exit(2) // failed at 'go help cmd' } - fmt.Fprintf(os.Stderr, "Unknown help topic %#q. Run 'go help'.\n", arg) - os.Exit(2) // failed at 'go help cmd' + if len(cmd.Commands) > 0 { + PrintUsage(os.Stdout, cmd) + } else { + tmpl(os.Stdout, helpTemplate, cmd) + } + // not exit 2: succeeded at 'go help cmd'. + return } -var usageTemplate = `Go is a tool for managing Go source code. +var usageTemplate = `{{.Long | trim}} Usage: - go command [arguments] + {{.UsageLine}} [arguments] The commands are: -{{range .}}{{if .Runnable}} +{{range .Commands}}{{if or (.Runnable) .Commands}} {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}} -Use "go help [command]" for more information about a command. - +Use "go help{{with .LongName}} {{.}}{{end}} " for more information about a command. +{{if eq (.UsageLine) "go"}} Additional help topics: -{{range .}}{{if not .Runnable}} +{{range .Commands}}{{if and (not .Runnable) (not .Commands)}} {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}} -Use "go help [topic]" for more information about that topic. - +Use "go help{{with .LongName}} {{.}}{{end}} " for more information about that topic. +{{end}} ` -var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}} +var helpTemplate = `{{if .Runnable}}usage: {{.UsageLine}} {{end}}{{.Long | trim}} ` var documentationTemplate = `{{range .}}{{if .Short}}{{.Short | capitalize}} -{{end}}{{if .Runnable}}Usage: +{{end}}{{if .Commands}}` + usageTemplate + `{{else}}{{if .Runnable}}Usage: - go {{.UsageLine}} + {{.UsageLine}} {{end}}{{.Long | trim}} -{{end}}` +{{end}}{{end}}` // commentWriter writes a Go comment to the underlying io.Writer, // using line comment form (//). @@ -171,8 +184,8 @@ func capitalize(s string) string { return string(unicode.ToTitle(r)) + s[n:] } -func PrintUsage(w io.Writer) { +func PrintUsage(w io.Writer, cmd *base.Command) { bw := bufio.NewWriter(w) - tmpl(bw, usageTemplate, base.Commands) + tmpl(bw, usageTemplate, cmd) bw.Flush() } diff --git a/libgo/go/cmd/go/internal/help/helpdoc.go b/libgo/go/cmd/go/internal/help/helpdoc.go index 6aa449a8e29..aff4ce12f6c 100644 --- a/libgo/go/cmd/go/internal/help/helpdoc.go +++ b/libgo/go/cmd/go/internal/help/helpdoc.go @@ -30,7 +30,7 @@ the C or C++ compiler, respectively, to use. var HelpPackages = &base.Command{ UsageLine: "packages", - Short: "package lists", + Short: "package lists and patterns", Long: ` Many commands apply to a set of packages: @@ -54,9 +54,11 @@ for packages to be built with the go tool: - "main" denotes the top-level package in a stand-alone executable. -- "all" expands to all package directories found in all the GOPATH +- "all" expands to all packages found in all the GOPATH trees. For example, 'go list all' lists all the packages on the local -system. +system. When using modules, "all" expands to all packages in +the main module and their dependencies, including dependencies +needed by tests of any of those. - "std" is like all but expands to just the packages in the standard Go library. @@ -193,6 +195,7 @@ using the named version control system, and then the path inside that repository. The supported version control systems are: Bazaar .bzr + Fossil .fossil Git .git Mercurial .hg Subversion .svn @@ -236,7 +239,7 @@ The meta tag should appear as early in the file as possible. In particular, it should appear before any raw JavaScript or CSS, to avoid confusing the go command's restricted parser. -The vcs is one of "git", "hg", "svn", etc, +The vcs is one of "bzr", "fossil", "git", "hg", "svn". The repo-root is the root of the version control system containing a scheme and not containing a .vcs qualifier. @@ -258,12 +261,22 @@ the go tool will verify that https://example.org/?go-get=1 contains the same meta tag and then git clone https://code.org/r/p/exproj into GOPATH/src/example.org. -New downloaded packages are written to the first directory listed in the GOPATH -environment variable (For more details see: 'go help gopath'). +When using GOPATH, downloaded packages are written to the first directory +listed in the GOPATH environment variable. +(See 'go help gopath-get' and 'go help gopath'.) -The go command attempts to download the version of the -package appropriate for the Go release being used. -Run 'go help get' for more. +When using modules, downloaded packages are stored in the module cache. +(See 'go help modules-get' and 'go help goproxy'.) + +When using modules, an additional variant of the go-import meta tag is +recognized and is preferred over those listing version control systems. +That variant uses "mod" as the vcs in the content value, as in: + + + +This tag means to fetch modules with paths beginning with example.org +from the module proxy available at the URL https://code.org/moduleproxy. +See 'go help goproxy' for details about the proxy protocol. Import path checking @@ -286,6 +299,9 @@ Import path checking is disabled for code found within vendor trees. This makes it possible to copy code into alternate locations in vendor trees without needing to update import comments. +Import path checking is also disabled when using modules. +Import path comments are obsoleted by the go.mod file's module statement. + See https://golang.org/s/go14customimport for details. `, } @@ -358,6 +374,12 @@ in the list. See https://golang.org/doc/code.html for an example. +GOPATH and Modules + +When using modules, GOPATH is no longer used for resolving imports. +However, it is still used to store downloaded source code (in GOPATH/pkg/mod) +and compiled commands (in GOPATH/bin). + Internal Directories Code in or below a directory named "internal" is importable only @@ -461,11 +483,21 @@ General-purpose environment variables: Examples are amd64, 386, arm, ppc64. GOBIN The directory where 'go install' will install a command. + GOCACHE + The directory where the go command will store cached + information for reuse in future builds. + GOFLAGS + A space-separated list of -flag=value settings to apply + to go commands by default, when the given flag is known by + the current command. Flags listed on the command-line + are applied after this list and therefore override it. GOOS The operating system for which to compile code. Examples are linux, darwin, windows, netbsd. GOPATH For more details see: 'go help gopath'. + GOPROXY + URL of Go module proxy. See 'go help goproxy'. GORACE Options for the race detector. See https://golang.org/doc/articles/race_detector.html. @@ -474,9 +506,6 @@ General-purpose environment variables: GOTMPDIR The directory where the go command will write temporary source files, packages, and binaries. - GOCACHE - The directory where the go command will store - cached information for reuse in future builds. Environment variables for use with cgo: @@ -523,6 +552,9 @@ Architecture-specific environment variables: GOMIPS For GOARCH=mips{,le}, whether to use floating point instructions. Valid values are hardfloat (default), softfloat. + GOMIPS64 + For GOARCH=mips64{,le}, whether to use floating point instructions. + Valid values are hardfloat (default), softfloat. Special-purpose environment variables: @@ -542,6 +574,20 @@ Special-purpose environment variables: Defined by Git. A colon-separated list of schemes that are allowed to be used with git fetch/clone. If set, any scheme not explicitly mentioned will be considered insecure by 'go get'. + +Additional information available from 'go env' but not read from the environment: + + GOEXE + The executable file name suffix (".exe" on Windows, "" on other systems). + GOHOSTARCH + The architecture (GOARCH) of the Go toolchain binaries. + GOHOSTOS + The operating system (GOOS) of the Go toolchain binaries. + GOMOD + The absolute path to the go.mod of the main module, + or the empty string if not using modules. + GOTOOLDIR + The directory where the go tools (compile, cover, doc, etc...) are installed. `, } @@ -651,6 +697,7 @@ The default location for cache data is a subdirectory named go-build in the standard user cache directory for the current operating system. Setting the GOCACHE environment variable overrides this default, and running 'go env GOCACHE' prints the current cache directory. +You can set the variable to 'off' to disable the cache. The go command periodically deletes cached data that has not been used recently. Running 'go clean -cache' deletes all cached data. diff --git a/libgo/go/cmd/go/internal/imports/build.go b/libgo/go/cmd/go/internal/imports/build.go new file mode 100644 index 00000000000..d1adf9440cb --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/build.go @@ -0,0 +1,211 @@ +// 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. + +// Copied from Go distribution src/go/build/build.go, syslist.go + +package imports + +import ( + "bytes" + "strings" + "unicode" +) + +var slashslash = []byte("//") + +// ShouldBuild reports whether it is okay to use this file, +// The rule is that in the file's leading run of // comments +// and blank lines, which must be followed by a blank line +// (to avoid including a Go package clause doc comment), +// lines beginning with '// +build' are taken as build directives. +// +// The file is accepted only if each such line lists something +// matching the file. For example: +// +// // +build windows linux +// +// marks the file as applicable only on Windows and Linux. +// +// If tags["*"] is true, then ShouldBuild will consider every +// build tag except "ignore" to be both true and false for +// the purpose of satisfying build tags, in order to estimate +// (conservatively) whether a file could ever possibly be used +// in any build. +// +func ShouldBuild(content []byte, tags map[string]bool) bool { + // Pass 1. Identify leading run of // comments and blank lines, + // which must be followed by a blank line. + end := 0 + 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 len(line) == 0 { // Blank line + end = len(content) - len(p) + continue + } + if !bytes.HasPrefix(line, slashslash) { // Not comment line + break + } + } + content = content[:end] + + // Pass 2. Process each line in the run. + p = content + allok := true + 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, slashslash) { + continue + } + line = bytes.TrimSpace(line[len(slashslash):]) + if len(line) > 0 && line[0] == '+' { + // Looks like a comment +line. + f := strings.Fields(string(line)) + if f[0] == "+build" { + ok := false + for _, tok := range f[1:] { + if matchTags(tok, tags) { + ok = true + } + } + if !ok { + allok = false + } + } + } + } + + return allok +} + +// matchTags reports whether the name is one of: +// +// tag (if tags[tag] is true) +// !tag (if tags[tag] is false) +// a comma-separated list of any of these +// +func matchTags(name string, tags map[string]bool) bool { + if name == "" { + return false + } + if i := strings.Index(name, ","); i >= 0 { + // comma-separated list + ok1 := matchTags(name[:i], tags) + ok2 := matchTags(name[i+1:], tags) + return ok1 && ok2 + } + if strings.HasPrefix(name, "!!") { // bad syntax, reject always + return false + } + if strings.HasPrefix(name, "!") { // negation + return len(name) > 1 && matchTag(name[1:], tags, false) + } + return matchTag(name, tags, true) +} + +// matchTag reports whether the tag name is valid and satisfied by tags[name]==want. +func matchTag(name string, tags map[string]bool, want bool) bool { + // 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 + } + } + + if tags["*"] && name != "" && name != "ignore" { + // Special case for gathering all possible imports: + // if we put * in the tags map then all tags + // except "ignore" are considered both present and not + // (so we return true no matter how 'want' is set). + return true + } + + have := tags[name] + if name == "linux" { + have = have || tags["android"] + } + return have == want +} + +// MatchFile returns false if the name contains a $GOOS or $GOARCH +// suffix which does not match the current system. +// The recognized name formats are: +// +// name_$(GOOS).* +// name_$(GOARCH).* +// name_$(GOOS)_$(GOARCH).* +// name_$(GOOS)_test.* +// name_$(GOARCH)_test.* +// name_$(GOOS)_$(GOARCH)_test.* +// +// An exception: if GOOS=android, then files with GOOS=linux are also matched. +// +// If tags["*"] is true, then MatchFile will consider all possible +// GOOS and GOARCH to be available and will consequently +// always return true. +func MatchFile(name string, tags map[string]bool) bool { + if tags["*"] { + return true + } + if dot := strings.Index(name, "."); dot != -1 { + name = name[:dot] + } + + // Before Go 1.4, a file called "linux.go" would be equivalent to having a + // build tag "linux" in that file. For Go 1.4 and beyond, we require this + // auto-tagging to apply only to files with a non-empty prefix, so + // "foo_linux.go" is tagged but "linux.go" is not. This allows new operating + // systems, such as android, to arrive without breaking existing code with + // innocuous source code in "android.go". The easiest fix: cut everything + // in the name before the initial _. + i := strings.Index(name, "_") + if i < 0 { + return true + } + name = name[i:] // ignore everything before first _ + + l := strings.Split(name, "_") + if n := len(l); n > 0 && l[n-1] == "test" { + l = l[:n-1] + } + n := len(l) + if n >= 2 && KnownOS[l[n-2]] && KnownArch[l[n-1]] { + return tags[l[n-2]] && tags[l[n-1]] + } + if n >= 1 && KnownOS[l[n-1]] { + return tags[l[n-1]] + } + if n >= 1 && KnownArch[l[n-1]] { + return tags[l[n-1]] + } + return true +} + +var KnownOS = make(map[string]bool) +var KnownArch = make(map[string]bool) + +func init() { + for _, v := range strings.Fields(goosList) { + KnownOS[v] = true + } + for _, v := range strings.Fields(goarchList) { + KnownArch[v] = true + } +} + +const goosList = "android darwin dragonfly freebsd 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 " diff --git a/libgo/go/cmd/go/internal/imports/read.go b/libgo/go/cmd/go/internal/imports/read.go new file mode 100644 index 00000000000..58c2abdc29a --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/read.go @@ -0,0 +1,249 @@ +// 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. + +// Copied from Go distribution src/go/build/read.go. + +package imports + +import ( + "bufio" + "errors" + "io" + "unicode/utf8" +) + +type importReader struct { + b *bufio.Reader + buf []byte + peek byte + err error + eof bool + nerr int +} + +func isIdent(c byte) bool { + return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= utf8.RuneSelf +} + +var ( + errSyntax = errors.New("syntax error") + errNUL = errors.New("unexpected NUL in input") +) + +// syntaxError records a syntax error, but only if an I/O error has not already been recorded. +func (r *importReader) syntaxError() { + if r.err == nil { + r.err = errSyntax + } +} + +// readByte reads the next byte from the input, saves it in buf, and returns it. +// If an error occurs, readByte records the error in r.err and returns 0. +func (r *importReader) readByte() byte { + c, err := r.b.ReadByte() + if err == nil { + r.buf = append(r.buf, c) + if c == 0 { + err = errNUL + } + } + if err != nil { + if err == io.EOF { + r.eof = true + } else if r.err == nil { + r.err = err + } + c = 0 + } + return c +} + +// peekByte returns the next byte from the input reader but does not advance beyond it. +// If skipSpace is set, peekByte skips leading spaces and comments. +func (r *importReader) peekByte(skipSpace bool) byte { + if r.err != nil { + if r.nerr++; r.nerr > 10000 { + panic("go/build: import reader looping") + } + return 0 + } + + // Use r.peek as first input byte. + // Don't just return r.peek here: it might have been left by peekByte(false) + // and this might be peekByte(true). + c := r.peek + if c == 0 { + c = r.readByte() + } + for r.err == nil && !r.eof { + if skipSpace { + // For the purposes of this reader, semicolons are never necessary to + // understand the input and are treated as spaces. + switch c { + case ' ', '\f', '\t', '\r', '\n', ';': + c = r.readByte() + continue + + case '/': + c = r.readByte() + if c == '/' { + for c != '\n' && r.err == nil && !r.eof { + c = r.readByte() + } + } else if c == '*' { + var c1 byte + for (c != '*' || c1 != '/') && r.err == nil { + if r.eof { + r.syntaxError() + } + c, c1 = c1, r.readByte() + } + } else { + r.syntaxError() + } + c = r.readByte() + continue + } + } + break + } + r.peek = c + return r.peek +} + +// nextByte is like peekByte but advances beyond the returned byte. +func (r *importReader) nextByte(skipSpace bool) byte { + c := r.peekByte(skipSpace) + r.peek = 0 + return c +} + +// readKeyword reads the given keyword from the input. +// If the keyword is not present, readKeyword records a syntax error. +func (r *importReader) readKeyword(kw string) { + r.peekByte(true) + for i := 0; i < len(kw); i++ { + if r.nextByte(false) != kw[i] { + r.syntaxError() + return + } + } + if isIdent(r.peekByte(false)) { + r.syntaxError() + } +} + +// readIdent reads an identifier from the input. +// If an identifier is not present, readIdent records a syntax error. +func (r *importReader) readIdent() { + c := r.peekByte(true) + if !isIdent(c) { + r.syntaxError() + return + } + for isIdent(r.peekByte(false)) { + r.peek = 0 + } +} + +// readString reads a quoted string literal from the input. +// If an identifier is not present, readString records a syntax error. +func (r *importReader) readString(save *[]string) { + switch r.nextByte(true) { + case '`': + start := len(r.buf) - 1 + for r.err == nil { + if r.nextByte(false) == '`' { + if save != nil { + *save = append(*save, string(r.buf[start:])) + } + break + } + if r.eof { + r.syntaxError() + } + } + case '"': + start := len(r.buf) - 1 + for r.err == nil { + c := r.nextByte(false) + if c == '"' { + if save != nil { + *save = append(*save, string(r.buf[start:])) + } + break + } + if r.eof || c == '\n' { + r.syntaxError() + } + if c == '\\' { + r.nextByte(false) + } + } + default: + r.syntaxError() + } +} + +// readImport reads an import clause - optional identifier followed by quoted string - +// from the input. +func (r *importReader) readImport(imports *[]string) { + c := r.peekByte(true) + if c == '.' { + r.peek = 0 + } else if isIdent(c) { + r.readIdent() + } + r.readString(imports) +} + +// ReadComments is like ioutil.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.peekByte(true) + if r.err == nil && !r.eof { + // Didn't reach EOF, so must have found a non-space byte. Remove it. + r.buf = r.buf[:len(r.buf)-1] + } + return r.buf, r.err +} + +// ReadImports is like ioutil.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.readKeyword("package") + r.readIdent() + for r.peekByte(true) == 'i' { + r.readKeyword("import") + if r.peekByte(true) == '(' { + r.nextByte(false) + for r.peekByte(true) != ')' && r.err == nil { + r.readImport(imports) + } + r.nextByte(false) + } else { + r.readImport(imports) + } + } + + // If we stopped successfully before EOF, we read a byte that told us we were done. + // Return all but that last byte, which would cause a syntax error if we let it through. + if r.err == nil && !r.eof { + return r.buf[:len(r.buf)-1], nil + } + + // If we stopped for a syntax error, consume the whole file so that + // we are sure we don't change the errors that go/parser returns. + if r.err == errSyntax && !reportSyntaxError { + r.err = nil + for r.err == nil && !r.eof { + r.readByte() + } + } + + return r.buf, r.err +} diff --git a/libgo/go/cmd/go/internal/imports/read_test.go b/libgo/go/cmd/go/internal/imports/read_test.go new file mode 100644 index 00000000000..6ea356f1ff0 --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/read_test.go @@ -0,0 +1,228 @@ +// 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. + +// Copied from Go distribution src/go/build/read.go. + +package imports + +import ( + "io" + "strings" + "testing" +) + +const quote = "`" + +type readTest struct { + // Test input contains ℙ where readImports should stop. + in string + err string +} + +var readImportsTests = []readTest{ + { + `package p`, + "", + }, + { + `package p; import "x"`, + "", + }, + { + `package p; import . "x"`, + "", + }, + { + `package p; import "x";ℙvar x = 1`, + "", + }, + { + `package p + + // comment + + import "x" + import _ "x" + import a "x" + + /* comment */ + + import ( + "x" /* comment */ + _ "x" + a "x" // comment + ` + quote + `x` + quote + ` + _ /*comment*/ ` + quote + `x` + quote + ` + a ` + quote + `x` + quote + ` + ) + import ( + ) + import () + import()import()import() + import();import();import() + + ℙvar x = 1 + `, + "", + }, +} + +var readCommentsTests = []readTest{ + { + `ℙpackage p`, + "", + }, + { + `ℙpackage p; import "x"`, + "", + }, + { + `ℙpackage p; import . "x"`, + "", + }, + { + `// foo + + /* bar */ + + /* quux */ // baz + + /*/ zot */ + + // asdf + ℙHello, world`, + "", + }, +} + +func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) { + for i, tt := range tests { + var in, testOut string + j := strings.Index(tt.in, "ℙ") + if j < 0 { + in = tt.in + testOut = tt.in + } else { + in = tt.in[:j] + tt.in[j+len("ℙ"):] + testOut = tt.in[:j] + } + r := strings.NewReader(in) + buf, err := read(r) + if err != nil { + if tt.err == "" { + t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf)) + continue + } + if !strings.Contains(err.Error(), tt.err) { + t.Errorf("#%d: err=%q, expected %q", i, err, tt.err) + continue + } + continue + } + if err == nil && tt.err != "" { + t.Errorf("#%d: success, expected %q", i, tt.err) + continue + } + + out := string(buf) + if out != testOut { + t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut) + } + } +} + +func TestReadImports(t *testing.T) { + testRead(t, readImportsTests, func(r io.Reader) ([]byte, error) { return ReadImports(r, true, nil) }) +} + +func TestReadComments(t *testing.T) { + testRead(t, readCommentsTests, ReadComments) +} + +var readFailuresTests = []readTest{ + { + `package`, + "syntax error", + }, + { + "package p\n\x00\nimport `math`\n", + "unexpected NUL in input", + }, + { + `package p; import`, + "syntax error", + }, + { + `package p; import "`, + "syntax error", + }, + { + "package p; import ` \n\n", + "syntax error", + }, + { + `package p; import "x`, + "syntax error", + }, + { + `package p; import _`, + "syntax error", + }, + { + `package p; import _ "`, + "syntax error", + }, + { + `package p; import _ "x`, + "syntax error", + }, + { + `package p; import .`, + "syntax error", + }, + { + `package p; import . "`, + "syntax error", + }, + { + `package p; import . "x`, + "syntax error", + }, + { + `package p; import (`, + "syntax error", + }, + { + `package p; import ("`, + "syntax error", + }, + { + `package p; import ("x`, + "syntax error", + }, + { + `package p; import ("x"`, + "syntax error", + }, +} + +func TestReadFailures(t *testing.T) { + // Errors should be reported (true arg to readImports). + testRead(t, readFailuresTests, func(r io.Reader) ([]byte, error) { return ReadImports(r, true, nil) }) +} + +func TestReadFailuresIgnored(t *testing.T) { + // Syntax errors should not be reported (false arg to readImports). + // Instead, entire file should be the output and no error. + // Convert tests not to return syntax errors. + tests := make([]readTest, len(readFailuresTests)) + copy(tests, readFailuresTests) + for i := range tests { + tt := &tests[i] + if !strings.Contains(tt.err, "NUL") { + tt.err = "" + } + } + testRead(t, tests, func(r io.Reader) ([]byte, error) { return ReadImports(r, false, nil) }) +} diff --git a/libgo/go/cmd/go/internal/imports/scan.go b/libgo/go/cmd/go/internal/imports/scan.go new file mode 100644 index 00000000000..d944e95724e --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/scan.go @@ -0,0 +1,96 @@ +// 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 imports + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "sort" + "strconv" + "strings" +) + +func ScanDir(dir string, tags map[string]bool) ([]string, []string, error) { + infos, err := ioutil.ReadDir(dir) + if err != nil { + return nil, nil, err + } + var files []string + for _, info := range infos { + name := info.Name() + if info.Mode().IsRegular() && !strings.HasPrefix(name, "_") && strings.HasSuffix(name, ".go") && MatchFile(name, tags) { + files = append(files, filepath.Join(dir, name)) + } + } + return scanFiles(files, tags, false) +} + +func ScanFiles(files []string, tags map[string]bool) ([]string, []string, error) { + return scanFiles(files, tags, true) +} + +func scanFiles(files []string, tags map[string]bool, explicitFiles bool) ([]string, []string, error) { + imports := make(map[string]bool) + testImports := make(map[string]bool) + numFiles := 0 +Files: + for _, name := range files { + r, err := os.Open(name) + if err != nil { + return nil, nil, err + } + var list []string + data, err := ReadImports(r, false, &list) + r.Close() + if err != nil { + return nil, nil, fmt.Errorf("reading %s: %v", name, err) + } + + // import "C" is implicit requirement of cgo tag. + // When listing files on the command line (explicitFiles=true) + // we do not apply build tag filtering but we still do apply + // cgo filtering, so no explicitFiles check here. + // Why? Because we always have, and it's not worth breaking + // that behavior now. + for _, path := range list { + if path == `"C"` && !tags["cgo"] && !tags["*"] { + continue Files + } + } + + if !explicitFiles && !ShouldBuild(data, tags) { + continue + } + numFiles++ + m := imports + if strings.HasSuffix(name, "_test.go") { + m = testImports + } + for _, p := range list { + q, err := strconv.Unquote(p) + if err != nil { + continue + } + m[q] = true + } + } + if numFiles == 0 { + return nil, nil, ErrNoGo + } + return keys(imports), keys(testImports), nil +} + +var ErrNoGo = fmt.Errorf("no Go source files") + +func keys(m map[string]bool) []string { + var list []string + for k := range m { + list = append(list, k) + } + sort.Strings(list) + return list +} diff --git a/libgo/go/cmd/go/internal/imports/scan_test.go b/libgo/go/cmd/go/internal/imports/scan_test.go new file mode 100644 index 00000000000..6a2ff62ba75 --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/scan_test.go @@ -0,0 +1,67 @@ +// 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 imports + +import ( + "internal/testenv" + "path/filepath" + "reflect" + "runtime" + "testing" +) + +func TestScan(t *testing.T) { + testenv.MustHaveGoBuild(t) + + imports, testImports, err := ScanDir(filepath.Join(runtime.GOROOT(), "src/encoding/json"), Tags()) + if err != nil { + t.Fatal(err) + } + foundBase64 := false + for _, p := range imports { + if p == "encoding/base64" { + foundBase64 = true + } + if p == "encoding/binary" { + // A dependency but not an import + t.Errorf("json reported as importing encoding/binary but does not") + } + if p == "net/http" { + // A test import but not an import + t.Errorf("json reported as importing encoding/binary but does not") + } + } + if !foundBase64 { + t.Errorf("json missing import encoding/base64 (%q)", imports) + } + + foundHTTP := false + for _, p := range testImports { + if p == "net/http" { + foundHTTP = true + } + if p == "unicode/utf16" { + // A package import but not a test import + t.Errorf("json reported as test-importing unicode/utf16 but does not") + } + } + if !foundHTTP { + t.Errorf("json missing test import net/http (%q)", testImports) + } +} + +func TestScanStar(t *testing.T) { + testenv.MustHaveGoBuild(t) + + imports, _, err := ScanDir("testdata/import1", map[string]bool{"*": true}) + if err != nil { + t.Fatal(err) + } + + want := []string{"import1", "import2", "import3", "import4"} + if !reflect.DeepEqual(imports, want) { + t.Errorf("ScanDir testdata/import1:\nhave %v\nwant %v", imports, want) + } +} diff --git a/libgo/go/cmd/go/internal/imports/tags.go b/libgo/go/cmd/go/internal/imports/tags.go new file mode 100644 index 00000000000..1c22a472b80 --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/tags.go @@ -0,0 +1,34 @@ +// 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 imports + +import "cmd/go/internal/cfg" + +var tags map[string]bool + +func Tags() map[string]bool { + if tags == nil { + tags = loadTags() + } + return tags +} + +func loadTags() map[string]bool { + tags := map[string]bool{ + cfg.BuildContext.GOOS: true, + cfg.BuildContext.GOARCH: true, + cfg.BuildContext.Compiler: true, + } + if cfg.BuildContext.CgoEnabled { + tags["cgo"] = true + } + for _, tag := range cfg.BuildContext.BuildTags { + tags[tag] = true + } + for _, tag := range cfg.BuildContext.ReleaseTags { + tags[tag] = true + } + return tags +} diff --git a/libgo/go/cmd/go/internal/imports/testdata/import1/x.go b/libgo/go/cmd/go/internal/imports/testdata/import1/x.go new file mode 100644 index 00000000000..98f9191053b --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/testdata/import1/x.go @@ -0,0 +1,3 @@ +package x + +import "import1" diff --git a/libgo/go/cmd/go/internal/imports/testdata/import1/x1.go b/libgo/go/cmd/go/internal/imports/testdata/import1/x1.go new file mode 100644 index 00000000000..6a9594aed03 --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/testdata/import1/x1.go @@ -0,0 +1,9 @@ +// +build blahblh +// +build linux +// +build !linux +// +build windows +// +build darwin + +package x + +import "import4" diff --git a/libgo/go/cmd/go/internal/imports/testdata/import1/x_darwin.go b/libgo/go/cmd/go/internal/imports/testdata/import1/x_darwin.go new file mode 100644 index 00000000000..a0c3fdd21b5 --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/testdata/import1/x_darwin.go @@ -0,0 +1,3 @@ +package xxxx + +import "import3" diff --git a/libgo/go/cmd/go/internal/imports/testdata/import1/x_windows.go b/libgo/go/cmd/go/internal/imports/testdata/import1/x_windows.go new file mode 100644 index 00000000000..63c508248fb --- /dev/null +++ b/libgo/go/cmd/go/internal/imports/testdata/import1/x_windows.go @@ -0,0 +1,3 @@ +package x + +import "import2" diff --git a/libgo/go/cmd/go/internal/list/list.go b/libgo/go/cmd/go/internal/list/list.go index 16e7f70d731..b3ba4edc650 100644 --- a/libgo/go/cmd/go/internal/list/list.go +++ b/libgo/go/cmd/go/internal/list/list.go @@ -7,23 +7,33 @@ package list import ( "bufio" + "bytes" "encoding/json" "io" "os" + "sort" "strings" "text/template" "cmd/go/internal/base" + "cmd/go/internal/cache" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/modload" + "cmd/go/internal/str" "cmd/go/internal/work" ) var CmdList = &base.Command{ - UsageLine: "list [-e] [-f format] [-json] [build flags] [packages]", - Short: "list packages", + // Note: -f -json -m are listed explicitly because they are the most common list flags. + // Do not send CLs removing them because they're covered by [list flags]. + UsageLine: "go list [-f format] [-json] [-m] [list flags] [build flags] [packages]", + Short: "list packages or modules", Long: ` -List lists the packages named by the import paths, one per line. +List lists the named packages, one per line. +The most commonly-used flags are -f and -json, which control the form +of the output printed for each package. Other list flags, documented below, +control more specific details. The default output shows the package import path: @@ -33,40 +43,46 @@ The default output shows the package import path: golang.org/x/net/html The -f flag specifies an alternate format for the list, using the -syntax of package template. The default output is equivalent to -f -'{{.ImportPath}}'. The struct being passed to the template is: +syntax of package template. The default output is equivalent +to -f '{{.ImportPath}}'. The struct being passed to the template is: type Package struct { - Dir string // directory containing package sources - ImportPath string // import path of package in dir - ImportComment string // path in import comment on package statement - Name string // package name - Doc string // package documentation string - Target string // install path - Shlib string // the shared library that contains this package (only set when -linkshared) - Goroot bool // is this package in the Go root? - Standard bool // is this package part of the standard Go library? - Stale bool // would 'go install' do anything for this package? - StaleReason string // explanation for Stale==true - Root string // Go root or Go path dir containing this package - ConflictDir string // this directory shadows Dir in $GOPATH - BinaryOnly bool // binary-only package: cannot be recompiled from sources + Dir string // directory containing package sources + ImportPath string // import path of package in dir + ImportComment string // path in import comment on package statement + Name string // package name + Doc string // package documentation string + Target string // install path + Shlib string // the shared library that contains this package (only set when -linkshared) + Goroot bool // is this package in the Go root? + Standard bool // is this package part of the standard Go library? + Stale bool // would 'go install' do anything for this package? + StaleReason string // explanation for Stale==true + Root string // Go root or Go path dir containing this package + ConflictDir string // this directory shadows Dir in $GOPATH + BinaryOnly bool // binary-only package: cannot be recompiled from sources + ForTest string // package is only for use in named test + Export string // file containing export data (when using -export) + Module *Module // info about package's containing module, if any (can be nil) + Match []string // command-line patterns matching this package + DepOnly bool // package is only a dependency, not explicitly listed // Source files - GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) - CgoFiles []string // .go sources files that import "C" - IgnoredGoFiles []string // .go sources ignored due to build constraints - CFiles []string // .c source files - CXXFiles []string // .cc, .cxx and .cpp source files - MFiles []string // .m source files - HFiles []string // .h, .hh, .hpp and .hxx source files - FFiles []string // .f, .F, .for and .f90 Fortran source files - SFiles []string // .s source files - SwigFiles []string // .swig files - SwigCXXFiles []string // .swigcxx files - SysoFiles []string // .syso object files to add to archive - TestGoFiles []string // _test.go files in package - XTestGoFiles []string // _test.go files outside package + GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) + CgoFiles []string // .go source files that import "C" + CompiledGoFiles []string // .go files presented to compiler (when using -compiled) + IgnoredGoFiles []string // .go source files ignored due to build constraints + CFiles []string // .c source files + CXXFiles []string // .cc, .cxx and .cpp source files + MFiles []string // .m source files + HFiles []string // .h, .hh, .hpp and .hxx source files + FFiles []string // .f, .F, .for and .f90 Fortran source files + SFiles []string // .s source files + SwigFiles []string // .swig files + SwigCXXFiles []string // .swigcxx files + SysoFiles []string // .syso object files to add to archive + TestGoFiles []string // _test.go files in package + XTestGoFiles []string // _test.go files outside package // Cgo directives CgoCFLAGS []string // cgo: flags for C compiler @@ -77,10 +93,11 @@ syntax of package template. The default output is equivalent to -f CgoPkgConfig []string // cgo: pkg-config names // Dependency information - Imports []string // import paths used by this package - Deps []string // all (recursively) imported dependencies - TestImports []string // imports from TestGoFiles - XTestImports []string // imports from XTestGoFiles + Imports []string // import paths used by this package + ImportMap map[string]string // map from source import to ImportPath (identity entries omitted) + Deps []string // all (recursively) imported dependencies + TestImports []string // imports from TestGoFiles + XTestImports []string // imports from XTestGoFiles // Error information Incomplete bool // this package or a dependency has an error @@ -92,7 +109,7 @@ Packages stored in vendor directories report an ImportPath that includes the path to the vendor directory (for example, "d/vendor/p" instead of "p"), so that the ImportPath uniquely identifies a given copy of a package. The Imports, Deps, TestImports, and XTestImports lists also contain these -expanded imports paths. See golang.org/s/go15vendor for more about vendoring. +expanded import paths. See golang.org/s/go15vendor for more about vendoring. The error information, if any, is @@ -102,22 +119,25 @@ The error information, if any, is Err string // the error itself } +The module information is a Module struct, defined in the discussion +of list -m below. + The template function "join" calls strings.Join. The template function "context" returns the build context, defined as: - type Context struct { - GOARCH string // target architecture - GOOS string // target operating system - GOROOT string // Go root - GOPATH string // Go path - CgoEnabled bool // whether cgo can be used - 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 - ReleaseTags []string // releases the current release is compatible with - InstallSuffix string // suffix to use in the name of the install dir - } + type Context struct { + GOARCH string // target architecture + GOOS string // target operating system + GOROOT string // Go root + GOPATH string // Go path + CgoEnabled bool // whether cgo can be used + 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 + ReleaseTags []string // releases the current release is compatible with + InstallSuffix string // suffix to use in the name of the install dir + } For more information about the meaning of these fields see the documentation for the go/build package's Context type. @@ -125,6 +145,18 @@ for the go/build package's Context type. The -json flag causes the package data to be printed in JSON format instead of using the template format. +The -compiled flag causes list to set CompiledGoFiles to the Go source +files presented to the compiler. Typically this means that it repeats +the files listed in GoFiles and then also adds the Go code generated +by processing CgoFiles and SwigFiles. The Imports list contains the +union of all imports from both GoFiles and CompiledGoFiles. + +The -deps flag causes list to iterate over not just the named packages +but also all their dependencies. It visits them in a depth-first post-order +traversal, so that a package is listed only after all its dependencies. +Packages not explicitly listed on the command line will have the DepOnly +field set to true. + The -e flag changes the handling of erroneous packages, those that cannot be found or are malformed. By default, the list command prints an error to standard error for each erroneous package and @@ -135,9 +167,120 @@ printing. Erroneous packages will have a non-empty ImportPath and a non-nil Error field; other information may or may not be missing (zeroed). +The -export flag causes list to set the Export field to the name of a +file containing up-to-date export information for the given package. + +The -find flag causes list to identify the named packages but not +resolve their dependencies: the Imports and Deps lists will be empty. + +The -test flag causes list to report not only the named packages +but also their test binaries (for packages with tests), to convey to +source code analysis tools exactly how test binaries are constructed. +The reported import path for a test binary is the import path of +the package followed by a ".test" suffix, as in "math/rand.test". +When building a test, it is sometimes necessary to rebuild certain +dependencies specially for that test (most commonly the tested +package itself). The reported import path of a package recompiled +for a particular test binary is followed by a space and the name of +the test binary in brackets, as in "math/rand [math/rand.test]" +or "regexp [sort.test]". The ForTest field is also set to the name +of the package being tested ("math/rand" or "sort" in the previous +examples). + +The Dir, Target, Shlib, Root, ConflictDir, and Export file paths +are all absolute paths. + +By default, the lists GoFiles, CgoFiles, and so on hold names of files in Dir +(that is, paths relative to Dir, not absolute paths). +The generated files added when using the -compiled and -test flags +are absolute paths referring to cached copies of generated Go source files. +Although they are Go source files, the paths may not end in ".go". + +The -m flag causes list to list modules instead of packages. + +When listing modules, the -f flag still specifies a format template +applied to a Go struct, but now a Module struct: + + type Module struct { + Path string // module path + Version string // module version + Versions []string // available module versions (with -versions) + Replace *Module // replaced by this module + Time *time.Time // time version was created + Update *Module // available update, if any (with -u) + Main bool // is this the main module? + Indirect bool // is this module only an indirect dependency of main module? + Dir string // directory holding files for this module, if any + GoMod string // path to go.mod file for this module, if any + Error *ModuleError // error loading module + } + + type ModuleError struct { + Err string // the error itself + } + +The default output is to print the module path and then +information about the version and replacement if any. +For example, 'go list -m all' might print: + + my/main/module + golang.org/x/text v0.3.0 => /tmp/text + rsc.io/pdf v0.1.1 + +The Module struct has a String method that formats this +line of output, so that the default format is equivalent +to -f '{{.String}}'. + +Note that when a module has been replaced, its Replace field +describes the replacement module, and its Dir field is set to +the replacement's source code, if present. (That is, if Replace +is non-nil, then Dir is set to Replace.Dir, with no access to +the replaced source code.) + +The -u flag adds information about available upgrades. +When the latest version of a given module is newer than +the current one, list -u sets the Module's Update field +to information about the newer module. +The Module's String method indicates an available upgrade by +formatting the newer version in brackets after the current version. +For example, 'go list -m -u all' might print: + + my/main/module + golang.org/x/text v0.3.0 [v0.4.0] => /tmp/text + rsc.io/pdf v0.1.1 [v0.1.2] + +(For tools, 'go list -m -u -json all' may be more convenient to parse.) + +The -versions flag causes list to set the Module's Versions field +to a list of all known versions of that module, ordered according +to semantic versioning, earliest to latest. The flag also changes +the default output format to display the module path followed by the +space-separated version list. + +The arguments to list -m are interpreted as a list of modules, not packages. +The main module is the module containing the current directory. +The active modules are the main module and its dependencies. +With no arguments, list -m shows the main module. +With arguments, list -m shows the modules specified by the arguments. +Any of the active modules can be specified by its module path. +The special pattern "all" specifies all the active modules, first the main +module and then dependencies sorted by module path. +A pattern containing "..." specifies the active modules whose +module paths match the pattern. +A query of the form path@version specifies the result of that query, +which is not limited to active modules. +See 'go help modules' for more about module queries. + +The template function "module" takes a single string argument +that must be a module path or query and returns the specified +module as a Module struct. If an error occurs, the result will +be a Module struct with a non-nil Error field. + For more about build flags, see 'go help build'. For more about specifying packages, see 'go help packages'. + +For more about modules, see 'go help modules'. `, } @@ -146,20 +289,43 @@ func init() { work.AddBuildFlags(CmdList) } -var listE = CmdList.Flag.Bool("e", false, "") -var listFmt = CmdList.Flag.String("f", "{{.ImportPath}}", "") -var listJson = CmdList.Flag.Bool("json", false, "") +var ( + listCompiled = CmdList.Flag.Bool("compiled", false, "") + listDeps = CmdList.Flag.Bool("deps", false, "") + listE = CmdList.Flag.Bool("e", false, "") + listExport = CmdList.Flag.Bool("export", false, "") + listFmt = CmdList.Flag.String("f", "", "") + listFind = CmdList.Flag.Bool("find", false, "") + listJson = CmdList.Flag.Bool("json", false, "") + listM = CmdList.Flag.Bool("m", false, "") + listU = CmdList.Flag.Bool("u", false, "") + listTest = CmdList.Flag.Bool("test", false, "") + listVersions = CmdList.Flag.Bool("versions", false, "") +) + var nl = []byte{'\n'} func runList(cmd *base.Command, args []string) { + modload.LoadTests = *listTest work.BuildInit() out := newTrackingWriter(os.Stdout) defer out.w.Flush() - var do func(*load.PackagePublic) + if *listFmt == "" { + if *listM { + *listFmt = "{{.String}}" + if *listVersions { + *listFmt = `{{.Path}}{{range .Versions}} {{.}}{{end}}` + } + } else { + *listFmt = "{{.ImportPath}}" + } + } + + var do func(interface{}) if *listJson { - do = func(p *load.PackagePublic) { - b, err := json.MarshalIndent(p, "", "\t") + do = func(x interface{}) { + b, err := json.MarshalIndent(x, "", "\t") if err != nil { out.Flush() base.Fatalf("%s", err) @@ -178,13 +344,14 @@ func runList(cmd *base.Command, args []string) { fm := template.FuncMap{ "join": strings.Join, "context": context, + "module": modload.ModuleInfo, } tmpl, err := template.New("main").Funcs(fm).Parse(*listFmt) if err != nil { base.Fatalf("%s", err) } - do = func(p *load.PackagePublic) { - if err := tmpl.Execute(out, p); err != nil { + do = func(x interface{}) { + if err := tmpl.Execute(out, x); err != nil { out.Flush() base.Fatalf("%s", err) } @@ -194,6 +361,62 @@ func runList(cmd *base.Command, args []string) { } } + if *listM { + // Module mode. + if *listCompiled { + base.Fatalf("go list -compiled cannot be used with -m") + } + if *listDeps { + // TODO(rsc): Could make this mean something with -m. + base.Fatalf("go list -deps cannot be used with -m") + } + if *listExport { + base.Fatalf("go list -export cannot be used with -m") + } + if *listFind { + base.Fatalf("go list -find cannot be used with -m") + } + if *listTest { + base.Fatalf("go list -test cannot be used with -m") + } + + if modload.Init(); !modload.Enabled() { + base.Fatalf("go list -m: not using modules") + } + modload.LoadBuildList() + + mods := modload.ListModules(args, *listU, *listVersions) + if !*listE { + for _, m := range mods { + if m.Error != nil { + base.Errorf("go list -m %s: %v", m.Path, m.Error.Err) + } + } + base.ExitIfErrors() + } + for _, m := range mods { + do(m) + } + return + } + + // Package mode (not -m). + if *listU { + base.Fatalf("go list -u can only be used with -m") + } + if *listVersions { + base.Fatalf("go list -versions can only be used with -m") + } + + // These pairings make no sense. + if *listFind && *listDeps { + base.Fatalf("go list -deps cannot be used with -find") + } + if *listFind && *listTest { + base.Fatalf("go list -test cannot be used with -find") + } + + load.IgnoreImports = *listFind var pkgs []*load.Package if *listE { pkgs = load.PackagesAndErrors(args) @@ -201,27 +424,178 @@ func runList(cmd *base.Command, args []string) { pkgs = load.Packages(args) } - // Estimate whether staleness information is needed, - // since it's a little bit of work to compute. + if cache.Default() == nil { + // These flags return file names pointing into the build cache, + // so the build cache must exist. + if *listCompiled { + base.Fatalf("go list -compiled requires build cache") + } + if *listExport { + base.Fatalf("go list -export requires build cache") + } + if *listTest { + base.Fatalf("go list -test requires build cache") + } + } + + if *listTest { + c := cache.Default() + // Add test binaries to packages to be listed. + for _, p := range pkgs { + if p.Error != nil { + continue + } + if len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 { + pmain, ptest, pxtest, err := load.GetTestPackagesFor(p, nil) + if err != nil { + if *listE { + pkgs = append(pkgs, &load.Package{ + PackagePublic: load.PackagePublic{ + ImportPath: p.ImportPath + ".test", + Error: &load.PackageError{Err: err.Error()}, + }, + }) + continue + } + base.Errorf("can't load test package: %s", err) + continue + } + pkgs = append(pkgs, pmain) + if ptest != nil { + pkgs = append(pkgs, ptest) + } + if pxtest != nil { + pkgs = append(pkgs, pxtest) + } + + data := *pmain.Internal.TestmainGo + h := cache.NewHash("testmain") + h.Write([]byte("testmain\n")) + h.Write(data) + out, _, err := c.Put(h.Sum(), bytes.NewReader(data)) + if err != nil { + base.Fatalf("%s", err) + } + pmain.GoFiles[0] = c.OutputFile(out) + } + } + } + + // Remember which packages are named on the command line. + cmdline := make(map[*load.Package]bool) + for _, p := range pkgs { + cmdline[p] = true + } + + if *listDeps { + // Note: This changes the order of the listed packages + // from "as written on the command line" to + // "a depth-first post-order traversal". + // (The dependency exploration order for a given node + // is alphabetical, same as listed in .Deps.) + // Note that -deps is applied after -test, + // so that you only get descriptions of tests for the things named + // explicitly on the command line, not for all dependencies. + pkgs = load.PackageList(pkgs) + } + + // Do we need to run a build to gather information? needStale := *listJson || strings.Contains(*listFmt, ".Stale") - if needStale { + if needStale || *listExport || *listCompiled { var b work.Builder b.Init() - b.ComputeStaleOnly = true + b.IsCmdList = true + b.NeedExport = *listExport + b.NeedCompiledGoFiles = *listCompiled a := &work.Action{} // TODO: Use pkgsFilter? for _, p := range pkgs { - a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p)) + if len(p.GoFiles)+len(p.CgoFiles) > 0 { + a.Deps = append(a.Deps, b.AutoAction(work.ModeInstall, work.ModeInstall, p)) + } } b.Do(a) } - for _, pkg := range pkgs { + for _, p := range pkgs { // Show vendor-expanded paths in listing - pkg.TestImports = pkg.Resolve(pkg.TestImports) - pkg.XTestImports = pkg.Resolve(pkg.XTestImports) + p.TestImports = p.Resolve(p.TestImports) + p.XTestImports = p.Resolve(p.XTestImports) + p.DepOnly = !cmdline[p] - do(&pkg.PackagePublic) + if *listCompiled { + p.Imports = str.StringList(p.Imports, p.Internal.CompiledImports) + } + } + + if *listTest { + all := pkgs + if !*listDeps { + all = load.PackageList(pkgs) + } + // Update import paths to distinguish the real package p + // from p recompiled for q.test. + // This must happen only once the build code is done + // looking at import paths, because it will get very confused + // if it sees these. + old := make(map[string]string) + for _, p := range all { + if p.ForTest != "" { + new := p.ImportPath + " [" + p.ForTest + ".test]" + old[new] = p.ImportPath + p.ImportPath = new + } + p.DepOnly = !cmdline[p] + } + // Update import path lists to use new strings. + m := make(map[string]string) + for _, p := range all { + for _, p1 := range p.Internal.Imports { + if p1.ForTest != "" { + m[old[p1.ImportPath]] = p1.ImportPath + } + } + for i, old := range p.Imports { + if new := m[old]; new != "" { + p.Imports[i] = new + } + } + for old := range m { + delete(m, old) + } + } + // Recompute deps lists using new strings, from the leaves up. + for _, p := range all { + deps := make(map[string]bool) + for _, p1 := range p.Internal.Imports { + deps[p1.ImportPath] = true + for _, d := range p1.Deps { + deps[d] = true + } + } + p.Deps = make([]string, 0, len(deps)) + for d := range deps { + p.Deps = append(p.Deps, d) + } + sort.Strings(p.Deps) + } + } + + // Record non-identity import mappings in p.ImportMap. + for _, p := range pkgs { + for i, srcPath := range p.Internal.RawImports { + path := p.Imports[i] + if path != srcPath { + if p.ImportMap == nil { + p.ImportMap = make(map[string]string) + } + p.ImportMap[srcPath] = path + } + } + } + + for _, p := range pkgs { + do(&p.PackagePublic) } } diff --git a/libgo/go/cmd/go/internal/load/flag.go b/libgo/go/cmd/go/internal/load/flag.go index 7ad4208ccc0..7534e65f54c 100644 --- a/libgo/go/cmd/go/internal/load/flag.go +++ b/libgo/go/cmd/go/internal/load/flag.go @@ -91,31 +91,3 @@ func (f *PerPackageFlag) For(p *Package) []string { } return flags } - -var cmdlineMatchers []func(*Package) bool - -// SetCmdlinePatterns records the set of patterns given on the command line, -// for use by the PerPackageFlags. -func SetCmdlinePatterns(args []string) { - setCmdlinePatterns(args, base.Cwd) -} - -func setCmdlinePatterns(args []string, cwd string) { - if len(args) == 0 { - args = []string{"."} - } - cmdlineMatchers = nil // allow reset for testing - for _, arg := range args { - cmdlineMatchers = append(cmdlineMatchers, MatchPackage(arg, cwd)) - } -} - -// isCmdlinePkg reports whether p is a package listed on the command line. -func isCmdlinePkg(p *Package) bool { - for _, m := range cmdlineMatchers { - if m(p) { - return true - } - } - return false -} diff --git a/libgo/go/cmd/go/internal/load/path.go b/libgo/go/cmd/go/internal/load/path.go index 45a9e7b242b..0211b284a40 100644 --- a/libgo/go/cmd/go/internal/load/path.go +++ b/libgo/go/cmd/go/internal/load/path.go @@ -32,22 +32,6 @@ func hasSubdir(root, dir string) (rel string, ok bool) { return filepath.ToSlash(dir[len(root):]), true } -// hasPathPrefix reports whether the path s begins with the -// elements in prefix. -func hasPathPrefix(s, prefix string) bool { - switch { - default: - return false - case len(s) == len(prefix): - return s == prefix - case len(s) > len(prefix): - if prefix != "" && prefix[len(prefix)-1] == '/' { - return strings.HasPrefix(s, prefix) - } - return s[len(prefix)] == '/' && s[:len(prefix)] == prefix - } -} - // expandPath returns the symlink-expanded form of path. func expandPath(p string) string { x, err := filepath.EvalSymlinks(p) diff --git a/libgo/go/cmd/go/internal/load/pkg.go b/libgo/go/cmd/go/internal/load/pkg.go index dfb1ff63afe..0579fd5ca53 100644 --- a/libgo/go/cmd/go/internal/load/pkg.go +++ b/libgo/go/cmd/go/internal/load/pkg.go @@ -22,9 +22,26 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" + "cmd/go/internal/modinfo" + "cmd/go/internal/search" "cmd/go/internal/str" ) +var ( + // module initialization hook; never nil, no-op if module use is disabled + ModInit func() + + // module hooks; nil if module use is disabled + ModBinDir func() string // return effective bin directory + ModLookup func(path string) (dir, realPath string, err error) // lookup effective meaning of import + ModPackageModuleInfo func(path string) *modinfo.ModulePublic // return module info for Package struct + ModImportPaths func(args []string) []*search.Match // expand import paths + ModPackageBuildInfo func(main string, deps []string) string // return module info to embed in binary + ModInfoProg func(info string) []byte // wrap module info in .go code for binary + ModImportFromFiles func([]string) // update go.mod to add modules for imports in these files + ModDirImportPath func(string) string // return effective import path for directory +) + var IgnoreImports bool // control whether we ignore imports in packages // A Package describes a single package found in a directory. @@ -37,18 +54,24 @@ type PackagePublic struct { // Note: These fields are part of the go command's public API. // See list.go. It is okay to add fields, but not to change or // remove existing ones. Keep in sync with list.go - Dir string `json:",omitempty"` // directory containing package sources - ImportPath string `json:",omitempty"` // import path of package in dir - ImportComment string `json:",omitempty"` // path in import comment on package statement - Name string `json:",omitempty"` // package name - Doc string `json:",omitempty"` // package documentation string - Target string `json:",omitempty"` // installed target for this package (may be executable) - Shlib string `json:",omitempty"` // the shared library that contains this package (only set when -linkshared) - Goroot bool `json:",omitempty"` // is this package found in the Go root? - Standard bool `json:",omitempty"` // is this package part of the standard Go library? - Root string `json:",omitempty"` // Go root or Go path dir containing this package - ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory - BinaryOnly bool `json:",omitempty"` // package cannot be recompiled + Dir string `json:",omitempty"` // directory containing package sources + ImportPath string `json:",omitempty"` // import path of package in dir + ImportComment string `json:",omitempty"` // path in import comment on package statement + Name string `json:",omitempty"` // package name + Doc string `json:",omitempty"` // package documentation string + Target string `json:",omitempty"` // installed target for this package (may be executable) + Shlib string `json:",omitempty"` // the shared library that contains this package (only set when -linkshared) + Root string `json:",omitempty"` // Go root or Go path dir containing this package + ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory + ForTest string `json:",omitempty"` // package is only for use in named test + Export string `json:",omitempty"` // file containing export data (set by go list -export) + Module *modinfo.ModulePublic `json:",omitempty"` // info about package's module, if any + Match []string `json:",omitempty"` // command-line patterns matching this package + Goroot bool `json:",omitempty"` // is this package found in the Go root? + Standard bool `json:",omitempty"` // is this package part of the standard Go library? + DepOnly bool `json:",omitempty"` // package is only as a dependency, not explicitly listed + BinaryOnly bool `json:",omitempty"` // package cannot be recompiled + Incomplete bool `json:",omitempty"` // was there an error loading this package or dependencies? // Stale and StaleReason remain here *only* for the list command. // They are only initialized in preparation for list execution. @@ -59,18 +82,19 @@ type PackagePublic struct { // Source files // If you add to this list you MUST add to p.AllFiles (below) too. // Otherwise file name security lists will not apply to any new additions. - GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) - CgoFiles []string `json:",omitempty"` // .go sources files that import "C" - IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints - CFiles []string `json:",omitempty"` // .c source files - CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files - MFiles []string `json:",omitempty"` // .m source files - HFiles []string `json:",omitempty"` // .h, .hh, .hpp and .hxx source files - FFiles []string `json:",omitempty"` // .f, .F, .for and .f90 Fortran source files - SFiles []string `json:",omitempty"` // .s source files - SwigFiles []string `json:",omitempty"` // .swig files - SwigCXXFiles []string `json:",omitempty"` // .swigcxx files - SysoFiles []string `json:",omitempty"` // .syso system object files added to package + GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles) + 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 + CFiles []string `json:",omitempty"` // .c source files + CXXFiles []string `json:",omitempty"` // .cc, .cpp and .cxx source files + MFiles []string `json:",omitempty"` // .m source files + HFiles []string `json:",omitempty"` // .h, .hh, .hpp and .hxx source files + FFiles []string `json:",omitempty"` // .f, .F, .for and .f90 Fortran source files + SFiles []string `json:",omitempty"` // .s source files + SwigFiles []string `json:",omitempty"` // .swig files + SwigCXXFiles []string `json:",omitempty"` // .swigcxx files + SysoFiles []string `json:",omitempty"` // .syso system object files added to package // Cgo directives CgoCFLAGS []string `json:",omitempty"` // cgo: flags for C compiler @@ -81,11 +105,12 @@ type PackagePublic struct { CgoPkgConfig []string `json:",omitempty"` // cgo: pkg-config names // Dependency information - Imports []string `json:",omitempty"` // import paths used by this package - Deps []string `json:",omitempty"` // all (recursively) imported dependencies + Imports []string `json:",omitempty"` // import paths used by this package + ImportMap map[string]string `json:",omitempty"` // map from source import to ImportPath (identity entries omitted) + Deps []string `json:",omitempty"` // all (recursively) imported dependencies // Error information - Incomplete bool `json:",omitempty"` // was there an error loading this package or dependencies? + // Incomplete is above, packed into the other bools Error *PackageError `json:",omitempty"` // error loading this package (not dependencies) DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies @@ -107,6 +132,7 @@ func (p *Package) AllFiles() []string { return str.StringList( p.GoFiles, p.CgoFiles, + // no p.CompiledGoFiles, because they are from GoFiles or generated by us p.IgnoredGoFiles, p.CFiles, p.CXXFiles, @@ -122,21 +148,33 @@ func (p *Package) AllFiles() []string { ) } +// Desc returns the package "description", for use in b.showOutput. +func (p *Package) Desc() string { + if p.ForTest != "" { + return p.ImportPath + " [" + p.ForTest + ".test]" + } + return p.ImportPath +} + type PackageInternal struct { // Unexported fields are not part of the public API. - Build *build.Package - Imports []*Package // this package's direct imports - RawImports []string // this package's original imports as they appear in the text of the program - 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 - Local bool // imported via local path (./ or ../) - LocalPrefix string // interpret ./ and ../ imports relative to this prefix - ExeName string // desired name for temporary executable - CoverMode string // preprocess Go source files with the coverage tool in this mode - CoverVars map[string]*CoverVar // variables created by coverage analysis - OmitDebug bool // tell linker not to write debug information - GobinSubdir bool // install target would be subdir of GOBIN + 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 + 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 + CmdlinePkgLiteral bool // package listed as literal on command line (not via wildcard) + Local bool // imported via local path (./ or ../) + LocalPrefix string // interpret ./ and ../ imports relative to this prefix + ExeName string // desired name for temporary executable + CoverMode string // preprocess Go source files with the coverage tool in this mode + CoverVars map[string]*CoverVar // variables created by coverage analysis + OmitDebug bool // tell linker not to write debug information + GobinSubdir bool // install target would be subdir of GOBIN + BuildInfo string // add this info to package main + TestmainGo *[]byte // content for _testmain.go Asmflags []string // -asmflags for this package Gcflags []string // -gcflags for this package @@ -224,7 +262,7 @@ func (p *Package) copyBuild(pp *build.Package) { // TODO? Target p.Goroot = pp.Goroot - p.Standard = p.Goroot && p.ImportPath != "" && isStandardImportPath(p.ImportPath) + p.Standard = p.Goroot && p.ImportPath != "" && search.IsStandardImportPath(p.ImportPath) p.GoFiles = pp.GoFiles p.CgoFiles = pp.CgoFiles p.IgnoredGoFiles = pp.IgnoredGoFiles @@ -253,24 +291,12 @@ func (p *Package) copyBuild(pp *build.Package) { p.XTestImports = pp.XTestImports if IgnoreImports { p.Imports = nil + p.Internal.RawImports = nil p.TestImports = nil p.XTestImports = nil } } -// isStandardImportPath reports whether $GOROOT/src/path should be considered -// part of the standard distribution. For historical reasons we allow people to add -// their own code to $GOROOT instead of using $GOPATH, but we assume that -// code will start with a domain name (dot in the first element). -func isStandardImportPath(path string) bool { - i := strings.Index(path, "/") - if i < 0 { - i = len(path) - } - elem := path[:i] - return !strings.Contains(elem, ".") -} - // A PackageError describes an error loading information about a package. type PackageError struct { ImportStack []string // shortest path from package named on command line to this one @@ -296,7 +322,9 @@ func (p *PackageError) Error() string { return "package " + strings.Join(p.ImportStack, "\n\timports ") + ": " + p.Err } -// An ImportStack is a stack of import paths. +// An ImportStack is a stack of import paths, possibly with the suffix " (test)" appended. +// The import path of a test package is the import path of the corresponding +// non-test package with the suffix "_test" added. type ImportStack []string func (s *ImportStack) Push(p string) { @@ -349,15 +377,17 @@ func ClearPackageCachePartial(args []string) { } } -// reloadPackage is like loadPackage but makes sure +// ReloadPackageNoFlags is like LoadPackageNoFlags but makes sure // not to use the package cache. -func ReloadPackage(arg string, stk *ImportStack) *Package { +// It is only for use by GOPATH-based "go get". +// TODO(rsc): When GOPATH-based "go get" is removed, delete this function. +func ReloadPackageNoFlags(arg string, stk *ImportStack) *Package { p := packageCache[arg] if p != nil { delete(packageCache, p.Dir) delete(packageCache, p.ImportPath) } - return LoadPackage(arg, stk) + return LoadPackageNoFlags(arg, stk) } // dirToImportPath returns the pseudo-import path we use for a package @@ -406,10 +436,53 @@ const ( // but possibly a local import path (an absolute file system path or one beginning // with ./ or ../). A local relative path is interpreted relative to srcDir. // It returns a *Package describing the package found in that directory. +// 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(path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package { stk.Push(path) defer stk.Pop() + if strings.HasPrefix(path, "mod/") { + // Paths beginning with "mod/" might accidentally + // look in the module cache directory tree in $GOPATH/pkg/mod/. + // This prefix is owned by the Go core for possible use in the + // standard library (since it does not begin with a domain name), + // so it's OK to disallow entirely. + return &Package{ + PackagePublic: PackagePublic{ + ImportPath: path, + Error: &PackageError{ + ImportStack: stk.Copy(), + Err: fmt.Sprintf("disallowed import path %q", path), + }, + }, + } + } + + if strings.Contains(path, "@") { + var text string + if cfg.ModulesEnabled { + text = "can only use path@version syntax with 'go get'" + } else { + text = "cannot use path@version syntax in GOPATH mode" + } + return &Package{ + PackagePublic: PackagePublic{ + ImportPath: path, + Error: &PackageError{ + ImportStack: stk.Copy(), + Err: text, + }, + }, + } + } + + parentPath := "" + if parent != nil { + parentPath = parent.ImportPath + } + // Determine canonical identifier for this package. // For a local import the identifier is the pseudo-import path // we create from the full directory to the package. @@ -418,8 +491,16 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo importPath := path origPath := path isLocal := build.IsLocalImport(path) + var modDir string + var modErr error if isLocal { importPath = dirToImportPath(filepath.Join(srcDir, path)) + } else if cfg.ModulesEnabled { + var p string + modDir, p, modErr = ModLookup(path) + if modErr == nil { + importPath = p + } } else if mode&ResolveImport != 0 { // We do our own path resolution, because we want to // find out the key to use in packageCache without the @@ -444,17 +525,31 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo // Load package. // Import always returns bp != nil, even if an error occurs, // in order to return partial information. - buildMode := build.ImportComment - if mode&ResolveImport == 0 || path != origPath { - // Not vendoring, or we already found the vendored path. - buildMode |= build.IgnoreVendor + var bp *build.Package + var err error + if modDir != "" { + bp, err = cfg.BuildContext.ImportDir(modDir, 0) + } else if modErr != nil { + bp = new(build.Package) + err = fmt.Errorf("unknown import path %q: %v", importPath, modErr) + } else if cfg.ModulesEnabled && path != "unsafe" { + bp = new(build.Package) + err = fmt.Errorf("unknown import path %q: internal error: module loader did not resolve import", importPath) + } else { + buildMode := build.ImportComment + if mode&ResolveImport == 0 || path != origPath { + // Not vendoring, or we already found the vendored path. + buildMode |= build.IgnoreVendor + } + bp, err = cfg.BuildContext.Import(path, srcDir, buildMode) } - bp, err := cfg.BuildContext.Import(path, srcDir, buildMode) bp.ImportPath = importPath if cfg.GOBIN != "" { bp.BinDir = cfg.GOBIN + } else if cfg.ModulesEnabled { + bp.BinDir = ModBinDir() } - if err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path && + if modDir == "" && err == nil && !isLocal && bp.ImportComment != "" && bp.ImportComment != path && !strings.Contains(path, "/vendor/") && !strings.HasPrefix(path, "vendor/") { err = fmt.Errorf("code in directory %s expects import %q", bp.Dir, bp.ImportComment) } @@ -463,7 +558,7 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo p = setErrorPos(p, importPos) } - if origPath != cleanImport(origPath) { + if modDir == "" && origPath != cleanImport(origPath) { p.Error = &PackageError{ ImportStack: stk.Copy(), Err: fmt.Sprintf("non-canonical import path: %q should be %q", origPath, pathpkg.Clean(origPath)), @@ -473,11 +568,11 @@ func LoadImport(path, srcDir string, parent *Package, stk *ImportStack, importPo } // Checked on every import because the rules depend on the code doing the importing. - if perr := disallowInternal(srcDir, p, stk); perr != p { + if perr := disallowInternal(srcDir, parent, parentPath, p, stk); perr != p { return setErrorPos(perr, importPos) } if mode&ResolveImport != 0 { - if perr := disallowVendor(srcDir, origPath, p, stk); perr != p { + if perr := disallowVendor(srcDir, parent, parentPath, origPath, p, stk); perr != p { return setErrorPos(perr, importPos) } } @@ -539,8 +634,14 @@ func isDir(path string) bool { // There are two different resolutions applied. // First, there is Go 1.5 vendoring (golang.org/s/go15vendor). // If vendor expansion doesn't trigger, then the path is also subject to -// Go 1.11 vgo legacy conversion (golang.org/issue/25069). +// Go 1.11 module legacy conversion (golang.org/issue/25069). func ResolveImportPath(parent *Package, path string) (found string) { + if cfg.ModulesEnabled { + if _, p, e := ModLookup(path); e == nil { + return p + } + return path + } found = VendoredImportPath(parent, path) if found != path { return found @@ -828,10 +929,11 @@ func reusePackage(p *Package, stk *ImportStack) *Package { return p } -// disallowInternal checks that srcDir is allowed to import p. +// disallowInternal checks that srcDir (containing package importerPath, if non-empty) +// 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, p *Package, stk *ImportStack) *Package { +func disallowInternal(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 @@ -874,23 +976,40 @@ func disallowInternal(srcDir string, p *Package, stk *ImportStack) *Package { if i > 0 { i-- // rewind over slash in ".../internal" } - parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)] - if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) { - return p - } - // Look for symlinks before reporting error. - srcDir = expandPath(srcDir) - parent = expandPath(parent) - if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) { - return p + if p.Module == nil { + parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)] + + if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) { + return p + } + + // Look for symlinks before reporting error. + srcDir = expandPath(srcDir) + parent = expandPath(parent) + if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) { + return p + } + } else { + // p is in a module, so make it available based on the importer's import path instead + // of the file path (https://golang.org/issue/23970). + if importerPath == "." { + // The importer is a list of command-line files. + // Pretend that the import path is the import path of the + // directory containing them. + importerPath = ModDirImportPath(importer.Dir) + } + parentOfInternal := p.ImportPath[:i] + if str.HasPathPrefix(importerPath, parentOfInternal) { + return p + } } // Internal is present, and srcDir is outside parent's tree. Not allowed. perr := *p perr.Error = &PackageError{ ImportStack: stk.Copy(), - Err: "use of internal package not allowed", + Err: "use of internal package " + p.ImportPath + " not allowed", } perr.Incomplete = true return &perr @@ -915,10 +1034,11 @@ func findInternal(path string) (index int, ok bool) { return 0, false } -// disallowVendor checks that srcDir is allowed to import p as path. +// disallowVendor checks that srcDir (containing package importerPath, if non-empty) +// is allowed to import p as path. // If the import is allowed, disallowVendor returns the original package p. // If not, it returns a new package containing just an appropriate error. -func disallowVendor(srcDir, path string, p *Package, stk *ImportStack) *Package { +func disallowVendor(srcDir string, importer *Package, importerPath, path string, p *Package, stk *ImportStack) *Package { // The stack includes p.ImportPath. // If that's the only thing on the stack, we started // with a name given on the command line, not an @@ -927,6 +1047,20 @@ func disallowVendor(srcDir, path string, p *Package, stk *ImportStack) *Package return p } + // Modules must not import vendor packages in the standard library, + // but the usual vendor visibility check will not catch them + // because the module loader presents them with an ImportPath starting + // with "golang_org/" instead of "vendor/". + if p.Standard && !importer.Standard && strings.HasPrefix(p.ImportPath, "golang_org") { + perr := *p + perr.Error = &PackageError{ + ImportStack: stk.Copy(), + Err: "use of vendored package " + path + " not allowed", + } + perr.Incomplete = true + return &perr + } + if perr := disallowVendorVisibility(srcDir, p, stk); perr != p { return perr } @@ -1057,26 +1191,6 @@ var foldPath = make(map[string]string) func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { p.copyBuild(bp) - // Decide whether p was listed on the command line. - // Given that load is called while processing the command line, - // you might think we could simply pass a flag down into load - // saying whether we are loading something named on the command - // line or something to satisfy an import. But the first load of a - // package named on the command line may be as a dependency - // of an earlier package named on the command line, not when we - // get to that package during command line processing. - // For example "go test fmt reflect" will load reflect as a dependency - // of fmt before it attempts to load as a command-line argument. - // Because loads are cached, the later load will be a no-op, - // so it is important that the first load can fill in CmdlinePkg correctly. - // Hence the call to an explicit matching check here. - p.Internal.CmdlinePkg = isCmdlinePkg(p) - - p.Internal.Asmflags = BuildAsmflags.For(p) - p.Internal.Gcflags = BuildGcflags.For(p) - p.Internal.Ldflags = BuildLdflags.For(p) - p.Internal.Gccgoflags = BuildGccgoflags.For(p) - // The localPrefix is the path we interpret ./ imports relative to. // Synthesized main packages sometimes override this. if p.Internal.Local { @@ -1113,11 +1227,45 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { return } _, elem := filepath.Split(p.Dir) + if cfg.ModulesEnabled { + // NOTE(rsc): Using p.ImportPath instead of p.Dir + // makes sure we install a package in the root of a + // cached module directory as that package name + // not name@v1.2.3. + // Using p.ImportPath instead of p.Dir + // is probably correct all the time, + // even for non-module-enabled code, + // but I'm not brave enough to change the + // non-module behavior this late in the + // release cycle. Maybe for Go 1.12. + // See golang.org/issue/26869. + _, elem = pathpkg.Split(p.ImportPath) + + // If this is example.com/mycmd/v2, it's more useful to install it as mycmd than as v2. + // See golang.org/issue/24667. + isVersion := func(v string) bool { + if len(v) < 2 || v[0] != 'v' || v[1] < '1' || '9' < v[1] { + return false + } + for i := 2; i < len(v); i++ { + if c := v[i]; c < '0' || '9' < c { + return false + } + } + return true + } + if isVersion(elem) { + _, elem = pathpkg.Split(pathpkg.Dir(p.ImportPath)) + } + } full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH { // Install cross-compiled binaries to subdirectories of bin. elem = full } + if p.Internal.Build.BinDir == "" && cfg.ModulesEnabled { + p.Internal.Build.BinDir = ModBinDir() + } if p.Internal.Build.BinDir != "" { // Install to GOBIN or bin of GOPATH entry. p.Target = filepath.Join(p.Internal.Build.BinDir, elem) @@ -1165,31 +1313,37 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { // Build augmented import list to add implicit dependencies. // Be careful not to add imports twice, just to avoid confusion. importPaths := p.Imports - addImport := func(path string) { + addImport := func(path string, forCompiler bool) { for _, p := range importPaths { if path == p { return } } importPaths = append(importPaths, path) + if forCompiler { + p.Internal.CompiledImports = append(p.Internal.CompiledImports, path) + } } - // Cgo translation adds imports of "runtime/cgo" and "syscall", + // 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") + addImport("runtime/cgo", true) } if p.UsesCgo() && (!p.Standard || !cgoSyscallExclude[p.ImportPath]) { - addImport("syscall") + addImport("syscall", true) } // SWIG adds imports of some standard packages. if p.UsesSwig() { if cfg.BuildContext.Compiler != "gccgo" { - addImport("runtime/cgo") + addImport("runtime/cgo", true) } - addImport("syscall") - addImport("sync") + addImport("syscall", true) + addImport("sync", true) // TODO: The .swig and .swigcxx files can use // %go_import directives to import other packages. @@ -1198,7 +1352,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { // The linker loads implicit dependencies. if p.Name == "main" && !p.Internal.ForceLibrary { for _, dep := range LinkerDeps(p) { - addImport(dep) + addImport(dep, false) } } @@ -1368,6 +1522,13 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) { setError(fmt.Sprintf("case-insensitive import collision: %q and %q", p.ImportPath, other)) return } + + if cfg.ModulesEnabled { + p.Module = ModPackageModuleInfo(p.ImportPath) + if p.Name == "main" { + p.Internal.BuildInfo = ModPackageBuildInfo(p.ImportPath, p.Deps) + } + } } // SafeArg reports whether arg is a "safe" command-line argument, @@ -1466,7 +1627,13 @@ func (p *Package) mkAbs(list []string) []string { // InternalGoFiles returns the list of Go files being built for the package, // using absolute paths. func (p *Package) InternalGoFiles() []string { - return p.mkAbs(str.StringList(p.GoFiles, p.CgoFiles, p.TestGoFiles, p.XTestGoFiles)) + return p.mkAbs(str.StringList(p.GoFiles, p.CgoFiles, p.TestGoFiles)) +} + +// InternalXGoFiles returns the list of Go files being built for the XTest package, +// using absolute paths. +func (p *Package) InternalXGoFiles() []string { + return p.mkAbs(p.XTestGoFiles) } // InternalGoFiles returns the list of all Go files possibly relevant for the package, @@ -1492,7 +1659,7 @@ func (p *Package) UsesCgo() bool { return len(p.CgoFiles) > 0 } -// packageList returns the list of packages in the dag rooted at roots +// PackageList returns the list of packages in the dag rooted at roots // as visited in a depth-first post-order traversal. func PackageList(roots []*Package) []*Package { seen := map[*Package]bool{} @@ -1514,6 +1681,42 @@ func PackageList(roots []*Package) []*Package { return all } +// 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 GetTestPackageList(roots []*Package) []*Package { + seen := map[*Package]bool{} + all := []*Package{} + var walk func(*Package) + walk = func(p *Package) { + if seen[p] { + return + } + seen[p] = true + for _, p1 := range p.Internal.Imports { + walk(p1) + } + all = append(all, p) + } + walkTest := func(root *Package, path string) { + var stk ImportStack + p1 := LoadImport(path, root.Dir, root, &stk, root.Internal.Build.TestImportPos[path], ResolveImport) + if p1.Error == nil { + walk(p1) + } + } + for _, root := range roots { + walk(root) + for _, path := range root.TestImports { + walkTest(root, path) + } + for _, path := range root.XTestImports { + walkTest(root, path) + } + } + return all +} + var cmdCache = map[string]*Package{} func ClearCmdCache() { @@ -1522,11 +1725,31 @@ func ClearCmdCache() { } } +// LoadPackage loads the package named by arg. +func LoadPackage(arg string, stk *ImportStack) *Package { + p := loadPackage(arg, stk) + setToolFlags(p) + return p +} + +// LoadPackageNoFlags is like LoadPackage +// but does not guarantee that the build tool flags are set in the result. +// It is only for use by GOPATH-based "go get" +// and is only appropriate for preliminary loading of packages. +// A real load using LoadPackage or (more likely) +// Packages, PackageAndErrors, or PackagesForBuild +// must be done before passing the package to any build +// steps, so that the tool flags can be set properly. +// TODO(rsc): When GOPATH-based "go get" is removed, delete this function. +func LoadPackageNoFlags(arg string, stk *ImportStack) *Package { + return loadPackage(arg, stk) +} + // loadPackage is like loadImport but is used for command-line arguments, // not for paths found in import statements. In addition to ordinary import paths, // loadPackage accepts pseudo-paths beginning with cmd/ to denote commands // in the Go command directory, as well as paths to those directories. -func LoadPackage(arg string, stk *ImportStack) *Package { +func loadPackage(arg string, stk *ImportStack) *Package { if build.IsLocalImport(arg) { dir := arg if !filepath.IsAbs(dir) { @@ -1573,8 +1796,12 @@ func LoadPackage(arg string, stk *ImportStack) *Package { // This lets you run go test ./ioutil in package io and be // referring to io/ioutil rather than a hypothetical import of // "./ioutil". - if build.IsLocalImport(arg) { - bp, _ := cfg.BuildContext.ImportDir(filepath.Join(base.Cwd, arg), build.FindOnly) + if build.IsLocalImport(arg) || filepath.IsAbs(arg) { + dir := arg + if !filepath.IsAbs(arg) { + dir = filepath.Join(base.Cwd, arg) + } + bp, _ := cfg.BuildContext.ImportDir(dir, build.FindOnly) if bp.ImportPath != "" && bp.ImportPath != "." { arg = bp.ImportPath } @@ -1583,7 +1810,7 @@ func LoadPackage(arg string, stk *ImportStack) *Package { return LoadImport(arg, base.Cwd, nil, stk, nil, 0) } -// packages returns the packages named by the +// Packages returns the packages named by the // command line arguments 'args'. If a named package // cannot be loaded at all (for example, if the directory does not exist), // then packages prints an error and does not include that @@ -1603,41 +1830,68 @@ func Packages(args []string) []*Package { return pkgs } -// packagesAndErrors is like 'packages' but returns a +// PackagesAndErrors is like 'packages' but returns a // *Package for every argument, even the ones that // cannot be loaded at all. // The packages that fail to load will have p.Error != nil. -func PackagesAndErrors(args []string) []*Package { - if len(args) > 0 && strings.HasSuffix(args[0], ".go") { - return []*Package{GoFilesPackage(args)} +func PackagesAndErrors(patterns []string) []*Package { + if len(patterns) > 0 && strings.HasSuffix(patterns[0], ".go") { + return []*Package{GoFilesPackage(patterns)} } - args = ImportPaths(args) + matches := ImportPaths(patterns) var ( pkgs []*Package stk ImportStack - seenArg = make(map[string]bool) seenPkg = make(map[*Package]bool) ) - for _, arg := range args { - if seenArg[arg] { - continue + for _, m := range matches { + for _, pkg := range m.Pkgs { + p := loadPackage(pkg, &stk) + p.Match = append(p.Match, m.Pattern) + p.Internal.CmdlinePkg = true + if m.Literal { + // Note: do not set = m.Literal unconditionally + // because maybe we'll see p matching both + // a literal and also a non-literal pattern. + p.Internal.CmdlinePkgLiteral = true + } + if seenPkg[p] { + continue + } + seenPkg[p] = true + pkgs = append(pkgs, p) } - seenArg[arg] = true - pkg := LoadPackage(arg, &stk) - if seenPkg[pkg] { - continue - } - seenPkg[pkg] = true - pkgs = append(pkgs, pkg) } + // Now that CmdlinePkg is set correctly, + // compute the effective flags for all loaded packages + // (not just the ones matching the patterns but also + // their dependencies). + setToolFlags(pkgs...) + return pkgs } -// packagesForBuild is like 'packages' but fails if any of -// the packages or their dependencies have errors +func setToolFlags(pkgs ...*Package) { + for _, p := range PackageList(pkgs) { + p.Internal.Asmflags = BuildAsmflags.For(p) + p.Internal.Gcflags = BuildGcflags.For(p) + p.Internal.Ldflags = BuildLdflags.For(p) + p.Internal.Gccgoflags = BuildGccgoflags.For(p) + } +} + +func ImportPaths(args []string) []*search.Match { + if ModInit(); cfg.ModulesEnabled { + return ModImportPaths(args) + } + return search.ImportPaths(args) +} + +// PackagesForBuild is like Packages but exits +// if any of the packages or their dependencies have errors // (cannot be built). func PackagesForBuild(args []string) []*Package { pkgs := PackagesAndErrors(args) @@ -1645,6 +1899,7 @@ func PackagesForBuild(args []string) []*Package { for _, pkg := range pkgs { if pkg.Error != nil { base.Errorf("can't load package: %s", pkg.Error) + printed[pkg.Error] = true } for _, err := range pkg.DepsErrors { // Since these are errors in dependencies, @@ -1682,7 +1937,8 @@ func PackagesForBuild(args []string) []*Package { // (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(gofiles []string) *Package { - // TODO: Remove this restriction. + ModInit() + for _, f := range gofiles { if !strings.HasSuffix(f, ".go") { base.Fatalf("named files must be .go files") @@ -1720,6 +1976,10 @@ func GoFilesPackage(gofiles []string) *Package { } ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil } + if cfg.ModulesEnabled { + ModImportFromFiles(gofiles) + } + var err error if dir == "" { dir = base.Cwd @@ -1730,6 +1990,11 @@ func GoFilesPackage(gofiles []string) *Package { } bp, err := ctxt.ImportDir(dir, 0) + if ModDirImportPath != nil { + // Use the effective import path of the directory + // for deciding visibility during pkg.load. + bp.ImportPath = ModDirImportPath(dir) + } pkg := new(Package) pkg.Internal.Local = true pkg.Internal.CmdlineFiles = true @@ -1739,6 +2004,7 @@ func GoFilesPackage(gofiles []string) *Package { pkg.Internal.LocalPrefix = dirToImportPath(dir) pkg.ImportPath = "command-line-arguments" pkg.Target = "" + pkg.Match = gofiles if pkg.Name == "main" { _, elem := filepath.Split(gofiles[0]) @@ -1748,152 +2014,12 @@ func GoFilesPackage(gofiles []string) *Package { } if cfg.GOBIN != "" { pkg.Target = filepath.Join(cfg.GOBIN, exe) + } else if cfg.ModulesEnabled { + pkg.Target = filepath.Join(ModBinDir(), exe) } } + setToolFlags(pkg) + return pkg } - -// GetTestPackagesFor returns package structs ptest, the package p plus -// its test files, and pxtest, the external tests of package p. -// pxtest may be nil. If there are no test files, forceTest decides -// whether this returns a new package struct or just returns p. -func GetTestPackagesFor(p *Package, forceTest bool) (ptest, pxtest *Package, err error) { - var imports, ximports []*Package - var stk ImportStack - stk.Push(p.ImportPath + " (test)") - rawTestImports := str.StringList(p.TestImports) - for i, path := range p.TestImports { - p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport) - if p1.Error != nil { - return nil, nil, p1.Error - } - if len(p1.DepsErrors) > 0 { - err := p1.DepsErrors[0] - err.Pos = "" // show full import stack - return nil, nil, err - } - 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. - err := &PackageError{ - ImportStack: testImportStack(stk[0], p1, p.ImportPath), - Err: "import cycle not allowed in test", - IsImportCycle: true, - } - return nil, nil, err - } - p.TestImports[i] = p1.ImportPath - imports = append(imports, p1) - } - stk.Pop() - stk.Push(p.ImportPath + "_test") - pxtestNeedsPtest := false - rawXTestImports := str.StringList(p.XTestImports) - for i, path := range p.XTestImports { - p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport) - if p1.Error != nil { - return nil, nil, p1.Error - } - if len(p1.DepsErrors) > 0 { - err := p1.DepsErrors[0] - err.Pos = "" // show full import stack - return nil, nil, err - } - if p1.ImportPath == p.ImportPath { - pxtestNeedsPtest = true - } else { - ximports = append(ximports, p1) - } - p.XTestImports[i] = p1.ImportPath - } - stk.Pop() - - // Test package. - if len(p.TestGoFiles) > 0 || forceTest { - ptest = new(Package) - *ptest = *p - ptest.GoFiles = nil - ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...) - ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...) - ptest.Target = "" - // Note: The preparation of the vet config requires that common - // indexes in ptest.Imports, ptest.Internal.Imports, and ptest.Internal.RawImports - // all line up (but RawImports can be shorter than the others). - // That is, for 0 ≤ i < len(RawImports), - // RawImports[i] is the import string in the program text, - // Imports[i] is the expanded import string (vendoring applied or relative path expanded away), - // and Internal.Imports[i] is the corresponding *Package. - // Any implicitly added imports appear in Imports and Internal.Imports - // but not RawImports (because they were not in the source code). - // We insert TestImports, imports, and rawTestImports at the start of - // these lists to preserve the alignment. - ptest.Imports = str.StringList(p.TestImports, p.Imports) - ptest.Internal.Imports = append(imports, p.Internal.Imports...) - ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports) - ptest.Internal.ForceLibrary = true - ptest.Internal.Build = new(build.Package) - *ptest.Internal.Build = *p.Internal.Build - m := map[string][]token.Position{} - for k, v := range p.Internal.Build.ImportPos { - m[k] = append(m[k], v...) - } - for k, v := range p.Internal.Build.TestImportPos { - m[k] = append(m[k], v...) - } - ptest.Internal.Build.ImportPos = m - } else { - ptest = p - } - - // External test package. - if len(p.XTestGoFiles) > 0 { - pxtest = &Package{ - PackagePublic: PackagePublic{ - Name: p.Name + "_test", - ImportPath: p.ImportPath + "_test", - Root: p.Root, - Dir: p.Dir, - GoFiles: p.XTestGoFiles, - Imports: p.XTestImports, - }, - Internal: PackageInternal{ - LocalPrefix: p.Internal.LocalPrefix, - Build: &build.Package{ - ImportPos: p.Internal.Build.XTestImportPos, - }, - Imports: ximports, - RawImports: rawXTestImports, - - Asmflags: p.Internal.Asmflags, - Gcflags: p.Internal.Gcflags, - Ldflags: p.Internal.Ldflags, - Gccgoflags: p.Internal.Gccgoflags, - }, - } - if pxtestNeedsPtest { - pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest) - } - } - - return ptest, pxtest, nil -} - -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 - } - } - // Can't happen, but in case it does... - stk = append(stk, "") - break - } - return stk -} diff --git a/libgo/go/cmd/go/internal/load/search.go b/libgo/go/cmd/go/internal/load/search.go index 595de079046..cf09c7b0a89 100644 --- a/libgo/go/cmd/go/internal/load/search.go +++ b/libgo/go/cmd/go/internal/load/search.go @@ -5,271 +5,16 @@ package load import ( - "cmd/go/internal/cfg" - "fmt" - "go/build" - "log" - "os" - "path" "path/filepath" - "regexp" "strings" + + "cmd/go/internal/search" ) -// allPackages returns all the packages that can be found -// under the $GOPATH directories and $GOROOT matching pattern. -// The pattern is either "all" (all packages), "std" (standard packages), -// "cmd" (standard commands), or a path including "...". -func allPackages(pattern string) []string { - pkgs := MatchPackages(pattern) - if len(pkgs) == 0 { - fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) - } - return pkgs -} - -// allPackagesInFS is like allPackages but is passed a pattern -// beginning ./ or ../, meaning it should scan the tree rooted -// at the given directory. There are ... in the pattern too. -func allPackagesInFS(pattern string) []string { - pkgs := MatchPackagesInFS(pattern) - if len(pkgs) == 0 { - fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) - } - return pkgs -} - -// MatchPackages returns a list of package paths matching pattern -// (see go help packages for pattern syntax). -func MatchPackages(pattern string) []string { - match := func(string) bool { return true } - treeCanMatch := func(string) bool { return true } - if !IsMetaPackage(pattern) { - match = matchPattern(pattern) - treeCanMatch = treeCanMatchPattern(pattern) - } - - have := map[string]bool{ - "builtin": true, // ignore pseudo-package that exists only for documentation - } - if !cfg.BuildContext.CgoEnabled { - have["runtime/cgo"] = true // ignore during walk - } - var pkgs []string - - for _, src := range cfg.BuildContext.SrcDirs() { - if (pattern == "std" || pattern == "cmd") && src != cfg.GOROOTsrc { - continue - } - src = filepath.Clean(src) + string(filepath.Separator) - root := src - if pattern == "cmd" { - root += "cmd" + string(filepath.Separator) - } - filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { - if err != nil || path == src { - return nil - } - - want := true - // Avoid .foo, _foo, and testdata directory trees. - _, elem := filepath.Split(path) - if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { - want = false - } - - name := filepath.ToSlash(path[len(src):]) - if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") { - // The name "std" is only the standard library. - // If the name is cmd, it's the root of the command tree. - want = false - } - if !treeCanMatch(name) { - want = false - } - - if !fi.IsDir() { - if fi.Mode()&os.ModeSymlink != 0 && want { - if target, err := os.Stat(path); err == nil && target.IsDir() { - fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path) - } - } - return nil - } - if !want { - return filepath.SkipDir - } - - if have[name] { - return nil - } - have[name] = true - if !match(name) { - return nil - } - pkg, err := cfg.BuildContext.ImportDir(path, 0) - if err != nil { - if _, noGo := err.(*build.NoGoError); noGo { - return nil - } - } - - // If we are expanding "cmd", skip main - // packages under cmd/vendor. At least as of - // March, 2017, there is one there for the - // vendored pprof tool. - if pattern == "cmd" && strings.HasPrefix(pkg.ImportPath, "cmd/vendor") && pkg.Name == "main" { - return nil - } - - pkgs = append(pkgs, name) - return nil - }) - } - return pkgs -} - -// MatchPackagesInFS returns a list of package paths matching pattern, -// which must begin with ./ or ../ -// (see go help packages for pattern syntax). -func MatchPackagesInFS(pattern string) []string { - // Find directory to begin the scan. - // Could be smarter but this one optimization - // is enough for now, since ... is usually at the - // end of a path. - i := strings.Index(pattern, "...") - dir, _ := path.Split(pattern[:i]) - - // pattern begins with ./ or ../. - // path.Clean will discard the ./ but not the ../. - // We need to preserve the ./ for pattern matching - // and in the returned import paths. - prefix := "" - if strings.HasPrefix(pattern, "./") { - prefix = "./" - } - match := matchPattern(pattern) - - var pkgs []string - filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { - if err != nil || !fi.IsDir() { - return nil - } - if path == dir { - // filepath.Walk starts at dir and recurses. For the recursive case, - // the path is the result of filepath.Join, which calls filepath.Clean. - // The initial case is not Cleaned, though, so we do this explicitly. - // - // This converts a path like "./io/" to "io". Without this step, running - // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io - // package, because prepending the prefix "./" to the unclean path would - // result in "././io", and match("././io") returns false. - path = filepath.Clean(path) - } - - // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..". - _, elem := filepath.Split(path) - dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." - if dot || strings.HasPrefix(elem, "_") || elem == "testdata" { - return filepath.SkipDir - } - - name := prefix + filepath.ToSlash(path) - if !match(name) { - return nil - } - - // We keep the directory if we can import it, or if we can't import it - // due to invalid Go source files. This means that directories containing - // parse errors will be built (and fail) instead of being silently skipped - // as not matching the pattern. Go 1.5 and earlier skipped, but that - // behavior means people miss serious mistakes. - // See golang.org/issue/11407. - if p, err := cfg.BuildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) { - if _, noGo := err.(*build.NoGoError); !noGo { - log.Print(err) - } - return nil - } - pkgs = append(pkgs, name) - return nil - }) - return pkgs -} - -// treeCanMatchPattern(pattern)(name) reports whether -// name or children of name can possibly match pattern. -// Pattern is the same limited glob accepted by matchPattern. -func treeCanMatchPattern(pattern string) func(name string) bool { - wildCard := false - if i := strings.Index(pattern, "..."); i >= 0 { - wildCard = true - pattern = pattern[:i] - } - return func(name string) bool { - return len(name) <= len(pattern) && hasPathPrefix(pattern, name) || - wildCard && strings.HasPrefix(name, pattern) - } -} - -// matchPattern(pattern)(name) reports whether -// name matches pattern. Pattern is a limited glob -// pattern in which '...' means 'any string' and there -// is no other special syntax. -// Unfortunately, there are two special cases. Quoting "go help packages": -// -// First, /... at the end of the pattern can match an empty string, -// so that net/... matches both net and packages in its subdirectories, like net/http. -// Second, any slash-separted pattern element containing a wildcard never -// participates in a match of the "vendor" element in the path of a vendored -// package, so that ./... does not match packages in subdirectories of -// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do. -// Note, however, that a directory named vendor that itself contains code -// is not a vendored package: cmd/vendor would be a command named vendor, -// and the pattern cmd/... matches it. -func matchPattern(pattern string) func(name string) bool { - // Convert pattern to regular expression. - // The strategy for the trailing /... is to nest it in an explicit ? expression. - // The strategy for the vendor exclusion is to change the unmatchable - // vendor strings to a disallowed code point (vendorChar) and to use - // "(anything but that codepoint)*" as the implementation of the ... wildcard. - // This is a bit complicated but the obvious alternative, - // namely a hand-written search like in most shell glob matchers, - // is too easy to make accidentally exponential. - // Using package regexp guarantees linear-time matching. - - const vendorChar = "\x00" - - if strings.Contains(pattern, vendorChar) { - return func(name string) bool { return false } - } - - re := regexp.QuoteMeta(pattern) - re = replaceVendor(re, vendorChar) - switch { - case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`): - re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)` - case re == vendorChar+`/\.\.\.`: - re = `(/vendor|/` + vendorChar + `/\.\.\.)` - case strings.HasSuffix(re, `/\.\.\.`): - re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?` - } - re = strings.Replace(re, `\.\.\.`, `[^`+vendorChar+`]*`, -1) - - reg := regexp.MustCompile(`^` + re + `$`) - - return func(name string) bool { - if strings.Contains(name, vendorChar) { - return false - } - return reg.MatchString(replaceVendor(name, vendorChar)) - } -} - // MatchPackage(pattern, cwd)(p) reports whether package p matches pattern in the working directory cwd. func MatchPackage(pattern, cwd string) func(*Package) bool { switch { - case strings.HasPrefix(pattern, "./") || strings.HasPrefix(pattern, "../") || pattern == "." || pattern == "..": + case search.IsRelativePath(pattern): // Split pattern into leading pattern-free directory path // (including all . and .. elements) and the final pattern. var dir string @@ -284,7 +29,7 @@ func MatchPackage(pattern, cwd string) func(*Package) bool { if pattern == "" { return func(p *Package) bool { return p.Dir == dir } } - matchPath := matchPattern(pattern) + matchPath := search.MatchPattern(pattern) return func(p *Package) bool { // Compute relative path to dir and see if it matches the pattern. rel, err := filepath.Rel(dir, p.Dir) @@ -305,81 +50,7 @@ func MatchPackage(pattern, cwd string) func(*Package) bool { case pattern == "cmd": return func(p *Package) bool { return p.Standard && strings.HasPrefix(p.ImportPath, "cmd/") } default: - matchPath := matchPattern(pattern) + matchPath := search.MatchPattern(pattern) return func(p *Package) bool { return matchPath(p.ImportPath) } } } - -// replaceVendor returns the result of replacing -// non-trailing vendor path elements in x with repl. -func replaceVendor(x, repl string) string { - if !strings.Contains(x, "vendor") { - return x - } - elem := strings.Split(x, "/") - for i := 0; i < len(elem)-1; i++ { - if elem[i] == "vendor" { - elem[i] = repl - } - } - return strings.Join(elem, "/") -} - -// ImportPaths returns the import paths to use for the given command line. -func ImportPaths(args []string) []string { - args = ImportPathsNoDotExpansion(args) - var out []string - for _, a := range args { - if strings.Contains(a, "...") { - if build.IsLocalImport(a) { - out = append(out, allPackagesInFS(a)...) - } else { - out = append(out, allPackages(a)...) - } - continue - } - out = append(out, a) - } - return out -} - -// ImportPathsNoDotExpansion returns the import paths to use for the given -// command line, but it does no ... expansion. -func ImportPathsNoDotExpansion(args []string) []string { - if cmdlineMatchers == nil { - SetCmdlinePatterns(args) - } - if len(args) == 0 { - return []string{"."} - } - var out []string - for _, a := range args { - // Arguments are supposed to be import paths, but - // as a courtesy to Windows developers, rewrite \ to / - // in command-line arguments. Handles .\... and so on. - if filepath.Separator == '\\' { - a = strings.Replace(a, `\`, `/`, -1) - } - - // Put argument in canonical form, but preserve leading ./. - if strings.HasPrefix(a, "./") { - a = "./" + path.Clean(a) - if a == "./." { - a = "." - } - } else { - a = path.Clean(a) - } - if IsMetaPackage(a) { - out = append(out, allPackages(a)...) - continue - } - out = append(out, a) - } - return out -} - -// IsMetaPackage checks if name is a reserved package name that expands to multiple packages. -func IsMetaPackage(name string) bool { - return name == "std" || name == "cmd" || name == "all" -} diff --git a/libgo/go/cmd/go/internal/load/test.go b/libgo/go/cmd/go/internal/load/test.go new file mode 100644 index 00000000000..0eab21b1761 --- /dev/null +++ b/libgo/go/cmd/go/internal/load/test.go @@ -0,0 +1,654 @@ +// 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 load + +import ( + "bytes" + "cmd/go/internal/base" + "cmd/go/internal/str" + "errors" + "fmt" + "go/ast" + "go/build" + "go/doc" + "go/parser" + "go/token" + "path/filepath" + "sort" + "strings" + "text/template" + "unicode" + "unicode/utf8" +) + +var TestMainDeps = []string{ + // Dependencies for testmain. + "os", + "testing", + "testing/internal/testdeps", +} + +type TestCover struct { + Mode string + Local bool + Pkgs []*Package + Paths []string + Vars []coverInfo + DeclVars func(*Package, ...string) map[string]*CoverVar +} + +// TestPackagesFor returns three packages: +// - ptest, the package p compiled with added "package p" test files. +// - pxtest, the result of compiling any "package p_test" (external) test files. +// - pmain, the package main corresponding to the test binary (running tests in ptest and pxtest). +// +// If the package has no "package p_test" test files, pxtest will be nil. +// If the non-test compilation of package p can be reused +// (for example, if there are no "package p" test files and +// package p need not be instrumented for coverage or any other reason), +// then the returned ptest == p. +// +// 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 GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Package, err error) { + var imports, ximports []*Package + var stk ImportStack + stk.Push(p.ImportPath + " (test)") + rawTestImports := str.StringList(p.TestImports) + for i, path := range p.TestImports { + p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.TestImportPos[path], ResolveImport) + if p1.Error != nil { + return nil, nil, nil, p1.Error + } + if len(p1.DepsErrors) > 0 { + err := p1.DepsErrors[0] + err.Pos = "" // show full import stack + return nil, nil, nil, err + } + 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. + err := &PackageError{ + ImportStack: testImportStack(stk[0], p1, p.ImportPath), + Err: "import cycle not allowed in test", + IsImportCycle: true, + } + return nil, nil, nil, err + } + p.TestImports[i] = p1.ImportPath + imports = append(imports, p1) + } + stk.Pop() + stk.Push(p.ImportPath + "_test") + pxtestNeedsPtest := false + rawXTestImports := str.StringList(p.XTestImports) + for i, path := range p.XTestImports { + p1 := LoadImport(path, p.Dir, p, &stk, p.Internal.Build.XTestImportPos[path], ResolveImport) + if p1.Error != nil { + return nil, nil, nil, p1.Error + } + if len(p1.DepsErrors) > 0 { + err := p1.DepsErrors[0] + err.Pos = "" // show full import stack + return nil, nil, nil, err + } + if p1.ImportPath == p.ImportPath { + pxtestNeedsPtest = true + } else { + ximports = append(ximports, p1) + } + p.XTestImports[i] = p1.ImportPath + } + stk.Pop() + + // Test package. + if len(p.TestGoFiles) > 0 || p.Name == "main" || cover != nil && cover.Local { + ptest = new(Package) + *ptest = *p + ptest.ForTest = p.ImportPath + ptest.GoFiles = nil + ptest.GoFiles = append(ptest.GoFiles, p.GoFiles...) + ptest.GoFiles = append(ptest.GoFiles, p.TestGoFiles...) + ptest.Target = "" + // Note: The preparation of the vet config requires that common + // indexes in ptest.Imports and ptest.Internal.RawImports + // all line up (but RawImports can be shorter than the others). + // That is, for 0 ≤ i < len(RawImports), + // RawImports[i] is the import string in the program text, and + // Imports[i] is the expanded import string (vendoring applied or relative path expanded away). + // Any implicitly added imports appear in Imports and Internal.Imports + // but not RawImports (because they were not in the source code). + // We insert TestImports, imports, and rawTestImports at the start of + // these lists to preserve the alignment. + // Note that p.Internal.Imports may not be aligned with p.Imports/p.Internal.RawImports, + // but we insert at the beginning there too just for consistency. + ptest.Imports = str.StringList(p.TestImports, p.Imports) + ptest.Internal.Imports = append(imports, p.Internal.Imports...) + ptest.Internal.RawImports = str.StringList(rawTestImports, p.Internal.RawImports) + ptest.Internal.ForceLibrary = true + ptest.Internal.Build = new(build.Package) + *ptest.Internal.Build = *p.Internal.Build + m := map[string][]token.Position{} + for k, v := range p.Internal.Build.ImportPos { + m[k] = append(m[k], v...) + } + for k, v := range p.Internal.Build.TestImportPos { + m[k] = append(m[k], v...) + } + ptest.Internal.Build.ImportPos = m + } else { + ptest = p + } + + // External test package. + if len(p.XTestGoFiles) > 0 { + pxtest = &Package{ + PackagePublic: PackagePublic{ + Name: p.Name + "_test", + ImportPath: p.ImportPath + "_test", + Root: p.Root, + Dir: p.Dir, + GoFiles: p.XTestGoFiles, + Imports: p.XTestImports, + ForTest: p.ImportPath, + }, + Internal: PackageInternal{ + LocalPrefix: p.Internal.LocalPrefix, + Build: &build.Package{ + ImportPos: p.Internal.Build.XTestImportPos, + }, + Imports: ximports, + RawImports: rawXTestImports, + + Asmflags: p.Internal.Asmflags, + Gcflags: p.Internal.Gcflags, + Ldflags: p.Internal.Ldflags, + Gccgoflags: p.Internal.Gccgoflags, + }, + } + if pxtestNeedsPtest { + pxtest.Internal.Imports = append(pxtest.Internal.Imports, ptest) + } + } + + // Build main package. + pmain = &Package{ + PackagePublic: PackagePublic{ + Name: "main", + Dir: p.Dir, + GoFiles: []string{"_testmain.go"}, + ImportPath: p.ImportPath + ".test", + Root: p.Root, + Imports: str.StringList(TestMainDeps), + }, + Internal: PackageInternal{ + Build: &build.Package{Name: "main"}, + Asmflags: p.Internal.Asmflags, + Gcflags: p.Internal.Gcflags, + Ldflags: p.Internal.Ldflags, + Gccgoflags: p.Internal.Gccgoflags, + }, + } + + // The generated main also imports testing, regexp, and os. + // Also the linker introduces implicit dependencies reported by LinkerDeps. + stk.Push("testmain") + deps := TestMainDeps // cap==len, so safe for append + for _, d := range LinkerDeps(p) { + deps = append(deps, d) + } + for _, dep := range deps { + if dep == ptest.ImportPath { + pmain.Internal.Imports = append(pmain.Internal.Imports, ptest) + } else { + p1 := LoadImport(dep, "", nil, &stk, nil, 0) + if p1.Error != nil { + return nil, nil, nil, p1.Error + } + pmain.Internal.Imports = append(pmain.Internal.Imports, p1) + } + } + stk.Pop() + + if cover != nil && cover.Pkgs != nil { + // Add imports, but avoid duplicates. + seen := map[*Package]bool{p: true, ptest: true} + for _, p1 := range pmain.Internal.Imports { + seen[p1] = true + } + for _, p1 := range cover.Pkgs { + if !seen[p1] { + seen[p1] = true + pmain.Internal.Imports = append(pmain.Internal.Imports, p1) + } + } + } + + // Do initial scan for metadata needed for writing _testmain.go + // Use that metadata to update the list of imports for package main. + // The list of imports is used by recompileForTest and by the loop + // afterward that gathers t.Cover information. + t, err := loadTestFuncs(ptest) + if err != nil { + return nil, nil, nil, err + } + t.Cover = cover + if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 { + pmain.Internal.Imports = append(pmain.Internal.Imports, ptest) + pmain.Imports = append(pmain.Imports, ptest.ImportPath) + t.ImportTest = true + } + if pxtest != nil { + pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest) + pmain.Imports = append(pmain.Imports, pxtest.ImportPath) + t.ImportXtest = true + } + + // Sort and dedup pmain.Imports. + // Only matters for go list -test output. + sort.Strings(pmain.Imports) + w := 0 + for _, path := range pmain.Imports { + if w == 0 || path != pmain.Imports[w-1] { + pmain.Imports[w] = path + w++ + } + } + pmain.Imports = pmain.Imports[:w] + pmain.Internal.RawImports = str.StringList(pmain.Imports) + + if ptest != p { + // We have made modifications to the package p being tested + // and are rebuilding p (as ptest). + // Arrange to rebuild all packages q such that + // the test depends on q and q depends on p. + // This makes sure that q sees the modifications to p. + // Strictly speaking, the rebuild is only necessary if the + // modifications to p change its export metadata, but + // determining that is a bit tricky, so we rebuild always. + recompileForTest(pmain, p, ptest, pxtest) + } + + // Should we apply coverage analysis locally, + // only for this package and only for this test? + // Yes, if -cover is on but -coverpkg has not specified + // a list of packages for global coverage. + if cover != nil && cover.Local { + ptest.Internal.CoverMode = cover.Mode + var coverFiles []string + coverFiles = append(coverFiles, ptest.GoFiles...) + coverFiles = append(coverFiles, ptest.CgoFiles...) + ptest.Internal.CoverVars = cover.DeclVars(ptest, coverFiles...) + } + + for _, cp := range pmain.Internal.Imports { + if len(cp.Internal.CoverVars) > 0 { + t.Cover.Vars = append(t.Cover.Vars, coverInfo{cp, cp.Internal.CoverVars}) + } + } + + data, err := formatTestmain(t) + if err != nil { + return nil, nil, nil, err + } + pmain.Internal.TestmainGo = &data + + return pmain, ptest, pxtest, nil +} + +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 + } + } + // Can't happen, but in case it does... + stk = append(stk, "") + break + } + return stk +} + +func recompileForTest(pmain, preal, ptest, pxtest *Package) { + // The "test copy" of preal is ptest. + // For each package that depends on preal, make a "test copy" + // that depends on ptest. And so on, up the dependency tree. + testCopy := map[*Package]*Package{preal: ptest} + for _, p := range PackageList([]*Package{pmain}) { + if p == preal { + continue + } + // Copy on write. + didSplit := p == pmain || p == pxtest + split := func() { + if didSplit { + return + } + didSplit = true + if testCopy[p] != nil { + panic("recompileForTest loop") + } + p1 := new(Package) + testCopy[p] = p1 + *p1 = *p + p1.ForTest = preal.ImportPath + p1.Internal.Imports = make([]*Package, len(p.Internal.Imports)) + copy(p1.Internal.Imports, p.Internal.Imports) + p1.Imports = make([]string, len(p.Imports)) + copy(p1.Imports, p.Imports) + p = p1 + p.Target = "" + } + + // Update p.Internal.Imports to use test copies. + for i, imp := range p.Internal.Imports { + if p1 := testCopy[imp]; p1 != nil && p1 != imp { + split() + p.Internal.Imports[i] = p1 + } + } + } +} + +// isTestFunc tells whether fn has the type of a testing function. arg +// specifies the parameter type we look for: B, M or T. +func isTestFunc(fn *ast.FuncDecl, arg string) bool { + if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 || + fn.Type.Params.List == nil || + len(fn.Type.Params.List) != 1 || + len(fn.Type.Params.List[0].Names) > 1 { + return false + } + ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr) + if !ok { + return false + } + // We can't easily check that the type is *testing.M + // because we don't know how testing has been imported, + // but at least check that it's *M or *something.M. + // Same applies for B and T. + if name, ok := ptr.X.(*ast.Ident); ok && name.Name == arg { + return true + } + if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == arg { + return true + } + return false +} + +// isTest tells whether name looks like a test (or benchmark, according to prefix). +// It is a Test (say) if there is a character after Test that is not a lower-case letter. +// We don't want TesticularCancer. +func isTest(name, prefix string) bool { + if !strings.HasPrefix(name, prefix) { + return false + } + if len(name) == len(prefix) { // "Test" is ok + return true + } + rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(rune) +} + +type coverInfo struct { + Package *Package + Vars map[string]*CoverVar +} + +// loadTestFuncs returns the testFuncs describing the tests that will be run. +func loadTestFuncs(ptest *Package) (*testFuncs, error) { + t := &testFuncs{ + Package: ptest, + } + for _, file := range ptest.TestGoFiles { + if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); err != nil { + return nil, err + } + } + for _, file := range ptest.XTestGoFiles { + if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); err != nil { + return nil, err + } + } + return t, nil +} + +// formatTestmain returns the content of the _testmain.go file for t. +func formatTestmain(t *testFuncs) ([]byte, error) { + var buf bytes.Buffer + if err := testmainTmpl.Execute(&buf, t); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +type testFuncs struct { + Tests []testFunc + Benchmarks []testFunc + Examples []testFunc + TestMain *testFunc + Package *Package + ImportTest bool + NeedTest bool + ImportXtest bool + NeedXtest bool + Cover *TestCover +} + +// ImportPath returns the import path of the package being tested, if it is within GOPATH. +// This is printed by the testing package when running benchmarks. +func (t *testFuncs) ImportPath() string { + pkg := t.Package.ImportPath + if strings.HasPrefix(pkg, "_/") { + return "" + } + if pkg == "command-line-arguments" { + return "" + } + return pkg +} + +// Covered returns a string describing which packages are being tested for coverage. +// If the covered package is the same as the tested package, it returns the empty string. +// Otherwise it is a comma-separated human-readable list of packages beginning with +// " in", ready for use in the coverage message. +func (t *testFuncs) Covered() string { + if t.Cover == nil || t.Cover.Paths == nil { + return "" + } + return " in " + strings.Join(t.Cover.Paths, ", ") +} + +// Tested returns the name of the package being tested. +func (t *testFuncs) Tested() string { + return t.Package.Name +} + +type testFunc struct { + Package string // imported package name (_test or _xtest) + Name string // function name + Output string // output, for examples + Unordered bool // output is allowed to be unordered. +} + +var testFileSet = token.NewFileSet() + +func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error { + f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments) + if err != nil { + return base.ExpandScanner(err) + } + for _, d := range f.Decls { + n, ok := d.(*ast.FuncDecl) + if !ok { + continue + } + if n.Recv != nil { + continue + } + name := n.Name.String() + switch { + case name == "TestMain": + if isTestFunc(n, "T") { + t.Tests = append(t.Tests, testFunc{pkg, name, "", false}) + *doImport, *seen = true, true + continue + } + err := checkTestFunc(n, "M") + if err != nil { + return err + } + if t.TestMain != nil { + return errors.New("multiple definitions of TestMain") + } + t.TestMain = &testFunc{pkg, name, "", false} + *doImport, *seen = true, true + case isTest(name, "Test"): + err := checkTestFunc(n, "T") + if err != nil { + return err + } + t.Tests = append(t.Tests, testFunc{pkg, name, "", false}) + *doImport, *seen = true, true + case isTest(name, "Benchmark"): + err := checkTestFunc(n, "B") + if err != nil { + return err + } + t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false}) + *doImport, *seen = true, true + } + } + ex := doc.Examples(f) + sort.Slice(ex, func(i, j int) bool { return ex[i].Order < ex[j].Order }) + for _, e := range ex { + *doImport = true // import test file whether executed or not + if e.Output == "" && !e.EmptyOutput { + // Don't run examples with no output. + continue + } + t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output, e.Unordered}) + *seen = true + } + return nil +} + +func checkTestFunc(fn *ast.FuncDecl, arg string) error { + if !isTestFunc(fn, arg) { + name := fn.Name.String() + pos := testFileSet.Position(fn.Pos()) + return fmt.Errorf("%s: wrong signature for %s, must be: func %s(%s *testing.%s)", pos, name, name, strings.ToLower(arg), arg) + } + return nil +} + +var testmainTmpl = template.Must(template.New("main").Parse(` +package main + +import ( +{{if not .TestMain}} + "os" +{{end}} + "testing" + "testing/internal/testdeps" + +{{if .ImportTest}} + {{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}} +{{end}} +{{if .ImportXtest}} + {{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}} +{{end}} +{{if .Cover}} +{{range $i, $p := .Cover.Vars}} + _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}} +{{end}} +{{end}} +) + +var tests = []testing.InternalTest{ +{{range .Tests}} + {"{{.Name}}", {{.Package}}.{{.Name}}}, +{{end}} +} + +var benchmarks = []testing.InternalBenchmark{ +{{range .Benchmarks}} + {"{{.Name}}", {{.Package}}.{{.Name}}}, +{{end}} +} + +var examples = []testing.InternalExample{ +{{range .Examples}} + {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}}, +{{end}} +} + +func init() { + testdeps.ImportPath = {{.ImportPath | printf "%q"}} +} + +{{if .Cover}} + +// Only updated by init functions, so no need for atomicity. +var ( + coverCounters = make(map[string][]uint32) + coverBlocks = make(map[string][]testing.CoverBlock) +) + +func init() { + {{range $i, $p := .Cover.Vars}} + {{range $file, $cover := $p.Vars}} + coverRegisterFile({{printf "%q" $cover.File}}, _cover{{$i}}.{{$cover.Var}}.Count[:], _cover{{$i}}.{{$cover.Var}}.Pos[:], _cover{{$i}}.{{$cover.Var}}.NumStmt[:]) + {{end}} + {{end}} +} + +func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts []uint16) { + if 3*len(counter) != len(pos) || len(counter) != len(numStmts) { + panic("coverage: mismatched sizes") + } + if coverCounters[fileName] != nil { + // Already registered. + return + } + coverCounters[fileName] = counter + block := make([]testing.CoverBlock, len(counter)) + for i := range counter { + block[i] = testing.CoverBlock{ + Line0: pos[3*i+0], + Col0: uint16(pos[3*i+2]), + Line1: pos[3*i+1], + Col1: uint16(pos[3*i+2]>>16), + Stmts: numStmts[i], + } + } + coverBlocks[fileName] = block +} +{{end}} + +func main() { +{{if .Cover}} + testing.RegisterCover(testing.Cover{ + Mode: {{printf "%q" .Cover.Mode}}, + Counters: coverCounters, + Blocks: coverBlocks, + CoveredPackages: {{printf "%q" .Covered}}, + }) +{{end}} + m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, examples) +{{with .TestMain}} + {{.Package}}.{{.Name}}(m) +{{else}} + os.Exit(m.Run()) +{{end}} +} + +`)) diff --git a/libgo/go/cmd/go/internal/modcmd/download.go b/libgo/go/cmd/go/internal/modcmd/download.go new file mode 100644 index 00000000000..cf42eff58a1 --- /dev/null +++ b/libgo/go/cmd/go/internal/modcmd/download.go @@ -0,0 +1,133 @@ +// 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 modcmd + +import ( + "cmd/go/internal/base" + "cmd/go/internal/modfetch" + "cmd/go/internal/modload" + "cmd/go/internal/module" + "cmd/go/internal/par" + "encoding/json" + "os" +) + +var cmdDownload = &base.Command{ + UsageLine: "go mod download [-dir] [-json] [modules]", + Short: "download modules to local cache", + Long: ` +Download downloads the named modules, which can be module patterns selecting +dependencies of the main module or module queries of the form path@version. +With no arguments, download applies to all dependencies of the main module. + +The go command will automatically download modules as needed during ordinary +execution. The "go mod download" command is useful mainly for pre-filling +the local cache or to compute the answers for a Go module proxy. + +By default, download reports errors to standard error but is otherwise silent. +The -json flag causes download to print a sequence of JSON objects +to standard output, describing each downloaded module (or failure), +corresponding to this Go struct: + + type Module struct { + Path string // module path + Version string // module version + Error string // error loading module + Info string // absolute path to cached .info file + GoMod string // absolute path to cached .mod file + Zip string // absolute path to cached .zip file + Dir string // absolute path to cached source root directory + Sum string // checksum for path, version (as in go.sum) + GoModSum string // checksum for go.mod (as in go.sum) + } + +See 'go help modules' for more about module queries. + `, +} + +var downloadJSON = cmdDownload.Flag.Bool("json", false, "") + +func init() { + cmdDownload.Run = runDownload // break init cycle +} + +type moduleJSON struct { + Path string `json:",omitempty"` + Version string `json:",omitempty"` + Error string `json:",omitempty"` + Info string `json:",omitempty"` + GoMod string `json:",omitempty"` + Zip string `json:",omitempty"` + Dir string `json:",omitempty"` + Sum string `json:",omitempty"` + GoModSum string `json:",omitempty"` +} + +func runDownload(cmd *base.Command, args []string) { + if len(args) == 0 { + args = []string{"all"} + } + + var mods []*moduleJSON + var work par.Work + listU := false + listVersions := false + for _, info := range modload.ListModules(args, listU, listVersions) { + if info.Replace != nil { + info = info.Replace + } + if info.Version == "" { + continue + } + m := &moduleJSON{ + Path: info.Path, + Version: info.Version, + } + mods = append(mods, m) + work.Add(m) + } + + work.Do(10, func(item interface{}) { + m := item.(*moduleJSON) + var err error + m.Info, err = modfetch.InfoFile(m.Path, m.Version) + if err != nil { + m.Error = err.Error() + return + } + m.GoMod, err = modfetch.GoModFile(m.Path, m.Version) + if err != nil { + m.Error = err.Error() + return + } + m.GoModSum, err = modfetch.GoModSum(m.Path, m.Version) + if err != nil { + m.Error = err.Error() + return + } + mod := module.Version{Path: m.Path, Version: m.Version} + m.Zip, err = modfetch.DownloadZip(mod) + if err != nil { + m.Error = err.Error() + return + } + m.Sum = modfetch.Sum(mod) + m.Dir, err = modfetch.Download(mod) + if err != nil { + m.Error = err.Error() + return + } + }) + + if *downloadJSON { + for _, m := range mods { + b, err := json.MarshalIndent(m, "", "\t") + if err != nil { + base.Fatalf("%v", err) + } + os.Stdout.Write(append(b, '\n')) + } + } +} diff --git a/libgo/go/cmd/go/internal/modcmd/edit.go b/libgo/go/cmd/go/internal/modcmd/edit.go new file mode 100644 index 00000000000..5fea3e48e08 --- /dev/null +++ b/libgo/go/cmd/go/internal/modcmd/edit.go @@ -0,0 +1,382 @@ +// 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 mod edit + +package modcmd + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/modfile" + "cmd/go/internal/modload" + "cmd/go/internal/module" +) + +var cmdEdit = &base.Command{ + UsageLine: "go mod edit [editing flags] [go.mod]", + Short: "edit go.mod from tools or scripts", + Long: ` +Edit provides a command-line interface for editing go.mod, +for use primarily by tools or scripts. It reads only go.mod; +it does not look up information about the modules involved. +By default, edit reads and writes the go.mod file of the main module, +but a different target file can be specified after the editing flags. + +The editing flags specify a sequence of editing operations. + +The -fmt flag reformats the go.mod file without making other changes. +This reformatting is also implied by any other modifications that use or +rewrite the go.mod file. The only time this flag is needed is if no other +flags are specified, as in 'go mod edit -fmt'. + +The -module flag changes the module's path (the go.mod file's module line). + +The -require=path@version and -droprequire=path flags +add and drop a requirement on the given module path and version. +Note that -require overrides any existing requirements on path. +These flags are mainly for tools that understand the module graph. +Users should prefer 'go get path@version' or 'go get path@none', +which make other go.mod adjustments as needed to satisfy +constraints imposed by other modules. + +The -exclude=path@version and -dropexclude=path@version flags +add and drop an exclusion for the given module path and version. +Note that -exclude=path@version is a no-op if that exclusion already exists. + +The -replace=old[@v]=new[@v] and -dropreplace=old[@v] flags +add and drop a replacement of the given module path and version pair. +If the @v in old@v is omitted, the replacement applies to all versions +with the old module path. If the @v in new@v is omitted, the new path +should be a local module root directory, not a module path. +Note that -replace overrides any existing replacements for old[@v]. + +The -require, -droprequire, -exclude, -dropexclude, -replace, +and -dropreplace editing flags may be repeated, and the changes +are applied in the order given. + +The -print flag prints the final go.mod in its text format instead of +writing it back to go.mod. + +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 + Version string + } + + type GoMod struct { + Module Module + Require []Require + Exclude []Module + Replace []Replace + } + + type Require struct { + Path string + Version string + Indirect bool + } + + type Replace struct { + Old Module + New Module + } + +Note that this only describes the go.mod file itself, not other modules +referred to indirectly. For the full set of modules available to a build, +use 'go list -m -json all'. + +For example, a tool can obtain the go.mod as a data structure by +parsing the output of 'go mod edit -json' and can then make changes +by invoking 'go mod edit' with -require, -exclude, and so on. + `, +} + +var ( + editFmt = cmdEdit.Flag.Bool("fmt", false, "") + // editGo = cmdEdit.Flag.String("go", "", "") + editJSON = cmdEdit.Flag.Bool("json", false, "") + editPrint = cmdEdit.Flag.Bool("print", false, "") + editModule = cmdEdit.Flag.String("module", "", "") + edits []func(*modfile.File) // edits specified in flags +) + +type flagFunc func(string) + +func (f flagFunc) String() string { return "" } +func (f flagFunc) Set(s string) error { f(s); return nil } + +func init() { + cmdEdit.Run = runEdit // break init cycle + + cmdEdit.Flag.Var(flagFunc(flagRequire), "require", "") + cmdEdit.Flag.Var(flagFunc(flagDropRequire), "droprequire", "") + cmdEdit.Flag.Var(flagFunc(flagExclude), "exclude", "") + cmdEdit.Flag.Var(flagFunc(flagDropReplace), "dropreplace", "") + cmdEdit.Flag.Var(flagFunc(flagReplace), "replace", "") + cmdEdit.Flag.Var(flagFunc(flagDropExclude), "dropexclude", "") + + base.AddBuildFlagsNX(&cmdEdit.Flag) +} + +func runEdit(cmd *base.Command, args []string) { + anyFlags := + *editModule != "" || + *editJSON || + *editPrint || + *editFmt || + len(edits) > 0 + + if !anyFlags { + base.Fatalf("go mod edit: no flags specified (see 'go help mod edit').") + } + + if *editJSON && *editPrint { + base.Fatalf("go mod edit: cannot use both -json and -print") + } + + if len(args) > 1 { + base.Fatalf("go mod edit: too many arguments") + } + var gomod string + if len(args) == 1 { + gomod = args[0] + } else { + modload.MustInit() + gomod = filepath.Join(modload.ModRoot, "go.mod") + } + + if *editModule != "" { + if err := module.CheckPath(*editModule); err != nil { + base.Fatalf("go mod: invalid -module: %v", err) + } + } + + // TODO(rsc): Implement -go= once we start advertising it. + + data, err := ioutil.ReadFile(gomod) + if err != nil { + base.Fatalf("go: %v", err) + } + + modFile, err := modfile.Parse(gomod, data, nil) + if err != nil { + base.Fatalf("go: errors parsing %s:\n%s", base.ShortPath(gomod), err) + } + + if *editModule != "" { + modFile.AddModuleStmt(modload.CmdModModule) + } + + if len(edits) > 0 { + for _, edit := range edits { + edit(modFile) + } + } + modFile.SortBlocks() + modFile.Cleanup() // clean file after edits + + if *editJSON { + editPrintJSON(modFile) + return + } + + data, err = modFile.Format() + if err != nil { + base.Fatalf("go: %v", err) + } + + if *editPrint { + os.Stdout.Write(data) + return + } + + if err := ioutil.WriteFile(gomod, data, 0666); err != nil { + base.Fatalf("go: %v", err) + } +} + +// parsePathVersion parses -flag=arg expecting arg to be path@version. +func parsePathVersion(flag, arg string) (path, version string) { + i := strings.Index(arg, "@") + if i < 0 { + base.Fatalf("go mod: -%s=%s: need path@version", flag, arg) + } + path, version = strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:]) + if err := module.CheckPath(path); err != nil { + base.Fatalf("go mod: -%s=%s: invalid path: %v", flag, arg, err) + } + + // We don't call modfile.CheckPathVersion, because that insists + // on versions being in semver form, but here we want to allow + // versions like "master" or "1234abcdef", which the go command will resolve + // the next time it runs (or during -fix). + // Even so, we need to make sure the version is a valid token. + if modfile.MustQuote(version) { + base.Fatalf("go mod: -%s=%s: invalid version %q", flag, arg, version) + } + + return path, version +} + +// parsePath parses -flag=arg expecting arg to be path (not path@version). +func parsePath(flag, arg string) (path string) { + if strings.Contains(arg, "@") { + base.Fatalf("go mod: -%s=%s: need just path, not path@version", flag, arg) + } + path = arg + if err := module.CheckPath(path); err != nil { + base.Fatalf("go mod: -%s=%s: invalid path: %v", flag, arg, err) + } + return path +} + +// parsePathVersionOptional parses path[@version], using adj to +// describe any errors. +func parsePathVersionOptional(adj, arg string, allowDirPath bool) (path, version string, err error) { + if i := strings.Index(arg, "@"); i < 0 { + path = arg + } else { + path, version = strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:]) + } + if err := module.CheckPath(path); err != nil { + if !allowDirPath || !modfile.IsDirectoryPath(path) { + return path, version, fmt.Errorf("invalid %s path: %v", adj, err) + } + } + if path != arg && modfile.MustQuote(version) { + return path, version, fmt.Errorf("invalid %s version: %q", adj, version) + } + return path, version, nil +} + +// flagRequire implements the -require flag. +func flagRequire(arg string) { + path, version := parsePathVersion("require", arg) + edits = append(edits, func(f *modfile.File) { + if err := f.AddRequire(path, version); err != nil { + base.Fatalf("go mod: -require=%s: %v", arg, err) + } + }) +} + +// flagDropRequire implements the -droprequire flag. +func flagDropRequire(arg string) { + path := parsePath("droprequire", arg) + edits = append(edits, func(f *modfile.File) { + if err := f.DropRequire(path); err != nil { + base.Fatalf("go mod: -droprequire=%s: %v", arg, err) + } + }) +} + +// flagExclude implements the -exclude flag. +func flagExclude(arg string) { + path, version := parsePathVersion("exclude", arg) + edits = append(edits, func(f *modfile.File) { + if err := f.AddExclude(path, version); err != nil { + base.Fatalf("go mod: -exclude=%s: %v", arg, err) + } + }) +} + +// flagDropExclude implements the -dropexclude flag. +func flagDropExclude(arg string) { + path, version := parsePathVersion("dropexclude", arg) + edits = append(edits, func(f *modfile.File) { + if err := f.DropExclude(path, version); err != nil { + base.Fatalf("go mod: -dropexclude=%s: %v", arg, err) + } + }) +} + +// flagReplace implements the -replace flag. +func flagReplace(arg string) { + var i int + if i = strings.Index(arg, "="); i < 0 { + base.Fatalf("go mod: -replace=%s: need old[@v]=new[@w] (missing =)", arg) + } + old, new := strings.TrimSpace(arg[:i]), strings.TrimSpace(arg[i+1:]) + if strings.HasPrefix(new, ">") { + base.Fatalf("go mod: -replace=%s: separator between old and new is =, not =>", arg) + } + oldPath, oldVersion, err := parsePathVersionOptional("old", old, false) + if err != nil { + base.Fatalf("go mod: -replace=%s: %v", arg, err) + } + newPath, newVersion, err := parsePathVersionOptional("new", new, true) + if err != nil { + base.Fatalf("go mod: -replace=%s: %v", arg, err) + } + if newPath == new && !modfile.IsDirectoryPath(new) { + base.Fatalf("go mod: -replace=%s: unversioned new path must be local directory", arg) + } + + edits = append(edits, func(f *modfile.File) { + if err := f.AddReplace(oldPath, oldVersion, newPath, newVersion); err != nil { + base.Fatalf("go mod: -replace=%s: %v", arg, err) + } + }) +} + +// flagDropReplace implements the -dropreplace flag. +func flagDropReplace(arg string) { + path, version, err := parsePathVersionOptional("old", arg, true) + if err != nil { + base.Fatalf("go mod: -dropreplace=%s: %v", arg, err) + } + edits = append(edits, func(f *modfile.File) { + if err := f.DropReplace(path, version); err != nil { + base.Fatalf("go mod: -dropreplace=%s: %v", arg, err) + } + }) +} + +// fileJSON is the -json output data structure. +type fileJSON struct { + Module module.Version + Require []requireJSON + Exclude []module.Version + Replace []replaceJSON +} + +type requireJSON struct { + Path string + Version string `json:",omitempty"` + Indirect bool `json:",omitempty"` +} + +type replaceJSON struct { + Old module.Version + New module.Version +} + +// editPrintJSON prints the -json output. +func editPrintJSON(modFile *modfile.File) { + var f fileJSON + f.Module = modFile.Module.Mod + for _, r := range modFile.Require { + f.Require = append(f.Require, requireJSON{Path: r.Mod.Path, Version: r.Mod.Version, Indirect: r.Indirect}) + } + for _, x := range modFile.Exclude { + f.Exclude = append(f.Exclude, x.Mod) + } + for _, r := range modFile.Replace { + f.Replace = append(f.Replace, replaceJSON{r.Old, r.New}) + } + data, err := json.MarshalIndent(&f, "", "\t") + if err != nil { + base.Fatalf("go: internal error: %v", err) + } + data = append(data, '\n') + os.Stdout.Write(data) +} diff --git a/libgo/go/cmd/go/internal/modcmd/graph.go b/libgo/go/cmd/go/internal/modcmd/graph.go new file mode 100644 index 00000000000..5825c6d8ca8 --- /dev/null +++ b/libgo/go/cmd/go/internal/modcmd/graph.go @@ -0,0 +1,73 @@ +// 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 mod graph + +package modcmd + +import ( + "bufio" + "os" + "sort" + + "cmd/go/internal/base" + "cmd/go/internal/modload" + "cmd/go/internal/module" + "cmd/go/internal/par" +) + +var cmdGraph = &base.Command{ + UsageLine: "go mod graph", + Short: "print module requirement graph", + Long: ` +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. + `, + Run: runGraph, +} + +func runGraph(cmd *base.Command, args []string) { + if len(args) > 0 { + base.Fatalf("go mod graph: graph takes no arguments") + } + modload.LoadBuildList() + + reqs := modload.MinReqs() + format := func(m module.Version) string { + if m.Version == "" { + return m.Path + } + return m.Path + "@" + m.Version + } + + // Note: using par.Work only to manage work queue. + // No parallelism here, so no locking. + var out []string + var deps int // index in out where deps start + var work par.Work + work.Add(modload.Target) + work.Do(1, func(item interface{}) { + m := item.(module.Version) + list, _ := reqs.Required(m) + for _, r := range list { + work.Add(r) + out = append(out, format(m)+" "+format(r)+"\n") + } + if m == modload.Target { + deps = len(out) + } + }) + + sort.Slice(out[deps:], func(i, j int) bool { + return out[deps+i][0] < out[deps+j][0] + }) + + 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 new file mode 100644 index 00000000000..f510a46262b --- /dev/null +++ b/libgo/go/cmd/go/internal/modcmd/init.go @@ -0,0 +1,41 @@ +// 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 mod init + +package modcmd + +import ( + "cmd/go/internal/base" + "cmd/go/internal/modload" + "os" +) + +var cmdInit = &base.Command{ + UsageLine: "go mod init [module]", + Short: "initialize new module in current directory", + Long: ` +Init initializes and writes a new go.mod to the current directory, +in effect creating a new module rooted at the current directory. +The file go.mod must not already exist. +If possible, init will guess the module path from import comments +(see 'go help importpath') or from version control configuration. +To override this guess, supply the module path as an argument. + `, + Run: runInit, +} + +func runInit(cmd *base.Command, args []string) { + modload.CmdModInit = true + if len(args) > 1 { + base.Fatalf("go mod init: too many arguments") + } + if len(args) == 1 { + modload.CmdModModule = args[0] + } + if _, err := os.Stat("go.mod"); err == nil { + base.Fatalf("go mod init: go.mod already exists") + } + modload.InitMod() // does all the hard work +} diff --git a/libgo/go/cmd/go/internal/modcmd/mod.go b/libgo/go/cmd/go/internal/modcmd/mod.go new file mode 100644 index 00000000000..f150cc9728a --- /dev/null +++ b/libgo/go/cmd/go/internal/modcmd/mod.go @@ -0,0 +1,31 @@ +// 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 modcmd implements the ``go mod'' command. +package modcmd + +import "cmd/go/internal/base" + +var CmdMod = &base.Command{ + UsageLine: "go mod", + Short: "module maintenance", + Long: `Go mod provides access to operations on modules. + +Note that support for modules is built into all the go commands, +not just 'go mod'. For example, day-to-day adding, removing, upgrading, +and downgrading of dependencies should be done using 'go get'. +See 'go help modules' for an overview of module functionality. + `, + + Commands: []*base.Command{ + cmdDownload, + cmdEdit, + cmdGraph, + cmdInit, + cmdTidy, + cmdVendor, + cmdVerify, + cmdWhy, + }, +} diff --git a/libgo/go/cmd/go/internal/modcmd/tidy.go b/libgo/go/cmd/go/internal/modcmd/tidy.go new file mode 100644 index 00000000000..f2063a9ea60 --- /dev/null +++ b/libgo/go/cmd/go/internal/modcmd/tidy.go @@ -0,0 +1,90 @@ +// 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 mod tidy + +package modcmd + +import ( + "fmt" + "os" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/modfetch" + "cmd/go/internal/modload" + "cmd/go/internal/module" +) + +var cmdTidy = &base.Command{ + UsageLine: "go mod tidy [-v]", + Short: "add missing and remove unused modules", + Long: ` +Tidy makes sure go.mod matches the source code in the module. +It adds any missing modules necessary to build the current module's +packages and dependencies, and it removes unused modules that +don't provide any relevant packages. It also adds any missing entries +to go.sum and removes any unnecessary ones. + +The -v flag causes tidy to print information about removed modules +to standard error. + `, +} + +func init() { + cmdTidy.Run = runTidy // break init cycle + cmdTidy.Flag.BoolVar(&cfg.BuildV, "v", false, "") +} + +func runTidy(cmd *base.Command, args []string) { + if len(args) > 0 { + base.Fatalf("go mod tidy: no arguments allowed") + } + + // LoadALL adds missing modules. + // Remove unused modules. + used := make(map[module.Version]bool) + for _, pkg := range modload.LoadALL() { + used[modload.PackageModule(pkg)] = true + } + used[modload.Target] = true // note: LoadALL initializes Target + + inGoMod := make(map[string]bool) + for _, r := range modload.ModFile().Require { + inGoMod[r.Mod.Path] = true + } + + var keep []module.Version + for _, m := range modload.BuildList() { + if used[m] { + keep = append(keep, m) + } else if cfg.BuildV && inGoMod[m.Path] { + fmt.Fprintf(os.Stderr, "unused %s\n", m.Path) + } + } + modload.SetBuildList(keep) + modTidyGoSum() // updates memory copy; WriteGoMod on next line flushes it out + modload.WriteGoMod() +} + +// modTidyGoSum resets the go.sum file content +// to be exactly what's needed for the current go.mod. +func modTidyGoSum() { + // Assuming go.sum already has at least enough from the successful load, + // we only have to tell modfetch what needs keeping. + reqs := modload.Reqs() + keep := make(map[module.Version]bool) + var walk func(module.Version) + walk = func(m module.Version) { + keep[m] = true + list, _ := reqs.Required(m) + for _, r := range list { + if !keep[r] { + walk(r) + } + } + } + walk(modload.Target) + modfetch.TrimGoSum(keep) +} diff --git a/libgo/go/cmd/go/internal/modcmd/vendor.go b/libgo/go/cmd/go/internal/modcmd/vendor.go new file mode 100644 index 00000000000..62e74585359 --- /dev/null +++ b/libgo/go/cmd/go/internal/modcmd/vendor.go @@ -0,0 +1,200 @@ +// 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 modcmd + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/modload" + "cmd/go/internal/module" +) + +var cmdVendor = &base.Command{ + UsageLine: "go mod vendor [-v]", + Short: "make vendored copy of dependencies", + Long: ` +Vendor resets the main module's vendor directory to include all packages +needed to build and test all the main module's packages. +It does not include test code for vendored packages. + +The -v flag causes vendor to print the names of vendored +modules and packages to standard error. + `, + Run: runVendor, +} + +func init() { + cmdVendor.Flag.BoolVar(&cfg.BuildV, "v", false, "") +} + +func runVendor(cmd *base.Command, args []string) { + if len(args) != 0 { + base.Fatalf("go mod vendor: vendor takes no arguments") + } + pkgs := modload.LoadVendor() + + vdir := filepath.Join(modload.ModRoot, "vendor") + if err := os.RemoveAll(vdir); err != nil { + base.Fatalf("go vendor: %v", err) + } + + modpkgs := make(map[module.Version][]string) + for _, pkg := range pkgs { + m := modload.PackageModule(pkg) + if m == modload.Target { + continue + } + modpkgs[m] = append(modpkgs[m], pkg) + } + + var buf bytes.Buffer + for _, m := range modload.BuildList()[1:] { + if pkgs := modpkgs[m]; len(pkgs) > 0 { + repl := "" + if r := modload.Replacement(m); r.Path != "" { + repl = " => " + r.Path + if r.Version != "" { + repl += " " + r.Version + } + } + fmt.Fprintf(&buf, "# %s %s%s\n", m.Path, m.Version, repl) + if cfg.BuildV { + fmt.Fprintf(os.Stderr, "# %s %s%s\n", m.Path, m.Version, repl) + } + for _, pkg := range pkgs { + fmt.Fprintf(&buf, "%s\n", pkg) + if cfg.BuildV { + fmt.Fprintf(os.Stderr, "%s\n", pkg) + } + vendorPkg(vdir, pkg) + } + } + } + if buf.Len() == 0 { + fmt.Fprintf(os.Stderr, "go: no dependencies to vendor\n") + return + } + if err := ioutil.WriteFile(filepath.Join(vdir, "modules.txt"), buf.Bytes(), 0666); err != nil { + base.Fatalf("go vendor: %v", err) + } +} + +func vendorPkg(vdir, pkg string) { + realPath := modload.ImportMap(pkg) + if realPath != pkg && modload.ImportMap(realPath) != "" { + fmt.Fprintf(os.Stderr, "warning: %s imported as both %s and %s; making two copies.\n", realPath, realPath, pkg) + } + + dst := filepath.Join(vdir, pkg) + src := modload.PackageDir(realPath) + if src == "" { + fmt.Fprintf(os.Stderr, "internal error: no pkg for %s -> %s\n", pkg, realPath) + } + copyDir(dst, src, matchNonTest) + if m := modload.PackageModule(realPath); m.Path != "" { + copyMetadata(m.Path, realPath, dst, src) + } +} + +type metakey struct { + modPath string + dst string +} + +var copiedMetadata = make(map[metakey]bool) + +// copyMetadata copies metadata files from parents of src to parents of dst, +// stopping after processing the src parent for modPath. +func copyMetadata(modPath, pkg, dst, src string) { + for parent := 0; ; parent++ { + if copiedMetadata[metakey{modPath, dst}] { + break + } + copiedMetadata[metakey{modPath, dst}] = true + if parent > 0 { + copyDir(dst, src, matchMetadata) + } + if modPath == pkg { + break + } + pkg = filepath.Dir(pkg) + dst = filepath.Dir(dst) + src = filepath.Dir(src) + } +} + +// metaPrefixes is the list of metadata file prefixes. +// Vendoring copies metadata files from parents of copied directories. +// Note that this list could be arbitrarily extended, and it is longer +// in other tools (such as godep or dep). By using this limited set of +// prefixes and also insisting on capitalized file names, we are trying +// to nudge people toward more agreement on the naming +// and also trying to avoid false positives. +var metaPrefixes = []string{ + "AUTHORS", + "CONTRIBUTORS", + "COPYLEFT", + "COPYING", + "COPYRIGHT", + "LEGAL", + "LICENSE", + "NOTICE", + "PATENTS", +} + +// matchMetadata reports whether info is a metadata file. +func matchMetadata(info os.FileInfo) bool { + name := info.Name() + for _, p := range metaPrefixes { + if strings.HasPrefix(name, p) { + return true + } + } + return false +} + +// matchNonTest reports whether info is any non-test file (including non-Go files). +func matchNonTest(info os.FileInfo) bool { + return !strings.HasSuffix(info.Name(), "_test.go") +} + +// copyDir copies all regular files satisfying match(info) from src to dst. +func copyDir(dst, src string, match func(os.FileInfo) bool) { + files, err := ioutil.ReadDir(src) + if err != nil { + base.Fatalf("go vendor: %v", err) + } + if err := os.MkdirAll(dst, 0777); err != nil { + base.Fatalf("go vendor: %v", err) + } + for _, file := range files { + if file.IsDir() || !file.Mode().IsRegular() || !match(file) { + continue + } + r, err := os.Open(filepath.Join(src, file.Name())) + if err != nil { + base.Fatalf("go vendor: %v", err) + } + w, err := os.Create(filepath.Join(dst, file.Name())) + if err != nil { + base.Fatalf("go vendor: %v", err) + } + if _, err := io.Copy(w, r); err != nil { + base.Fatalf("go vendor: %v", err) + } + r.Close() + if err := w.Close(); err != nil { + base.Fatalf("go vendor: %v", err) + } + } +} diff --git a/libgo/go/cmd/go/internal/modcmd/verify.go b/libgo/go/cmd/go/internal/modcmd/verify.go new file mode 100644 index 00000000000..381c18d58f1 --- /dev/null +++ b/libgo/go/cmd/go/internal/modcmd/verify.go @@ -0,0 +1,96 @@ +// 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 modcmd + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + + "cmd/go/internal/base" + "cmd/go/internal/dirhash" + "cmd/go/internal/modfetch" + "cmd/go/internal/modload" + "cmd/go/internal/module" +) + +var cmdVerify = &base.Command{ + UsageLine: "go mod verify", + Short: "verify dependencies have expected content", + Long: ` +Verify checks that the dependencies of the current module, +which are stored in a local downloaded source cache, have not been +modified since being downloaded. If all the modules are unmodified, +verify prints "all modules verified." Otherwise it reports which +modules have been changed and causes 'go mod' to exit with a +non-zero status. + `, + Run: runVerify, +} + +func runVerify(cmd *base.Command, args []string) { + if len(args) != 0 { + // NOTE(rsc): Could take a module pattern. + base.Fatalf("go mod verify: verify takes no arguments") + } + ok := true + for _, mod := range modload.LoadBuildList()[1:] { + ok = verifyMod(mod) && ok + } + if ok { + fmt.Printf("all modules verified\n") + } +} + +func verifyMod(mod module.Version) bool { + ok := true + zip, zipErr := modfetch.CachePath(mod, "zip") + if zipErr == nil { + _, zipErr = os.Stat(zip) + } + dir, dirErr := modfetch.DownloadDir(mod) + if dirErr == nil { + _, dirErr = os.Stat(dir) + } + data, err := ioutil.ReadFile(zip + "hash") + if err != nil { + if zipErr != nil && os.IsNotExist(zipErr) && dirErr != nil && os.IsNotExist(dirErr) { + // Nothing downloaded yet. Nothing to verify. + return true + } + base.Errorf("%s %s: missing ziphash: %v", mod.Path, mod.Version, err) + return false + } + h := string(bytes.TrimSpace(data)) + + if zipErr != nil && os.IsNotExist(zipErr) { + // ok + } else { + hZ, err := dirhash.HashZip(zip, dirhash.DefaultHash) + if err != nil { + base.Errorf("%s %s: %v", mod.Path, mod.Version, err) + return false + } else if hZ != h { + base.Errorf("%s %s: zip has been modified (%v)", mod.Path, mod.Version, zip) + ok = false + } + } + if dirErr != nil && os.IsNotExist(dirErr) { + // ok + } else { + hD, err := dirhash.HashDir(dir, mod.Path+"@"+mod.Version, dirhash.DefaultHash) + if err != nil { + + base.Errorf("%s %s: %v", mod.Path, mod.Version, err) + return false + } + if hD != h { + base.Errorf("%s %s: dir has been modified (%v)", mod.Path, mod.Version, dir) + ok = false + } + } + return ok +} diff --git a/libgo/go/cmd/go/internal/modcmd/why.go b/libgo/go/cmd/go/internal/modcmd/why.go new file mode 100644 index 00000000000..03e0a039bc5 --- /dev/null +++ b/libgo/go/cmd/go/internal/modcmd/why.go @@ -0,0 +1,121 @@ +// 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 modcmd + +import ( + "cmd/go/internal/base" + "cmd/go/internal/modload" + "cmd/go/internal/module" + "fmt" + "strings" +) + +var cmdWhy = &base.Command{ + UsageLine: "go mod why [-m] [-vendor] packages...", + Short: "explain why packages or modules are needed", + Long: ` +Why shows a shortest path in the import graph from the main module to +each of the listed packages. If the -m flag is given, why treats the +arguments as a list of modules and finds a path to any package in each +of the modules. + +By default, why queries the graph of packages matched by "go list all", +which includes tests for reachable packages. The -vendor flag causes why +to exclude tests of dependencies. + +The output is a sequence of stanzas, one for each package or module +name on the command line, separated by blank lines. Each stanza begins +with a comment line "# package" or "# module" giving the target +package or module. Subsequent lines give a path through the import +graph, one package per line. If the package or module is not +referenced from the main module, the stanza will display a single +parenthesized note indicating that fact. + +For example: + + $ go mod why golang.org/x/text/language golang.org/x/text/encoding + # golang.org/x/text/language + rsc.io/quote + rsc.io/sampler + golang.org/x/text/language + + # golang.org/x/text/encoding + (main module does not need package golang.org/x/text/encoding) + $ + `, +} + +var ( + whyM = cmdWhy.Flag.Bool("m", false, "") + whyVendor = cmdWhy.Flag.Bool("vendor", false, "") +) + +func init() { + cmdWhy.Run = runWhy // break init cycle +} + +func runWhy(cmd *base.Command, args []string) { + loadALL := modload.LoadALL + if *whyVendor { + loadALL = modload.LoadVendor + } + if *whyM { + listU := false + listVersions := false + for _, arg := range args { + if strings.Contains(arg, "@") { + base.Fatalf("go mod why: module query not allowed") + } + } + mods := modload.ListModules(args, listU, listVersions) + byModule := make(map[module.Version][]string) + for _, path := range loadALL() { + m := modload.PackageModule(path) + if m.Path != "" { + byModule[m] = append(byModule[m], path) + } + } + sep := "" + for _, m := range mods { + best := "" + bestDepth := 1000000000 + for _, path := range byModule[module.Version{Path: m.Path, Version: m.Version}] { + d := modload.WhyDepth(path) + if d > 0 && d < bestDepth { + best = path + bestDepth = d + } + } + why := modload.Why(best) + if why == "" { + vendoring := "" + if *whyVendor { + vendoring = " to vendor" + } + why = "(main module does not need" + vendoring + " module " + m.Path + ")\n" + } + fmt.Printf("%s# %s\n%s", sep, m.Path, why) + sep = "\n" + } + } else { + matches := modload.ImportPaths(args) // resolve to packages + loadALL() // rebuild graph, from main module (not from named packages) + sep := "" + for _, m := range matches { + for _, path := range m.Pkgs { + why := modload.Why(path) + if why == "" { + vendoring := "" + if *whyVendor { + vendoring = " to vendor" + } + why = "(main module does not need" + vendoring + " package " + path + ")\n" + } + fmt.Printf("%s# %s\n%s", sep, path, why) + sep = "\n" + } + } + } +} diff --git a/libgo/go/cmd/go/internal/modconv/convert.go b/libgo/go/cmd/go/internal/modconv/convert.go new file mode 100644 index 00000000000..6fc6718e473 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/convert.go @@ -0,0 +1,90 @@ +// 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 ( + "fmt" + "os" + "sort" + "strings" + "sync" + + "cmd/go/internal/base" + "cmd/go/internal/modfetch" + "cmd/go/internal/modfile" + "cmd/go/internal/module" + "cmd/go/internal/par" + "cmd/go/internal/semver" +) + +// ConvertLegacyConfig converts legacy config to modfile. +// The file argument is slash-delimited. +func ConvertLegacyConfig(f *modfile.File, file string, data []byte) error { + i := strings.LastIndex(file, "/") + j := -2 + if i >= 0 { + j = strings.LastIndex(file[:i], "/") + } + convert := Converters[file[i+1:]] + if convert == nil && j != -2 { + convert = Converters[file[j+1:]] + } + if convert == nil { + return fmt.Errorf("unknown legacy config file %s", file) + } + mf, err := convert(file, data) + if err != nil { + return fmt.Errorf("parsing %s: %v", file, err) + } + + // Convert requirements block, which may use raw SHA1 hashes as versions, + // to valid semver requirement list, respecting major versions. + var work par.Work + for _, r := range mf.Require { + m := r.Mod + if m.Path == "" { + continue + } + work.Add(r.Mod) + } + + var ( + mu sync.Mutex + need = make(map[string]string) + ) + work.Do(10, func(item interface{}) { + r := item.(module.Version) + repo, info, err := modfetch.ImportRepoRev(r.Path, r.Version) + if err != nil { + fmt.Fprintf(os.Stderr, "go: converting %s: stat %s@%s: %v\n", base.ShortPath(file), r.Path, r.Version, err) + return + } + mu.Lock() + path := repo.ModulePath() + // Don't use semver.Max here; need to preserve +incompatible suffix. + if v, ok := need[path]; !ok || semver.Compare(v, info.Version) < 0 { + need[path] = info.Version + } + mu.Unlock() + }) + + var paths []string + for path := range need { + paths = append(paths, path) + } + sort.Strings(paths) + for _, path := range paths { + f.AddNewRequire(path, need[path], false) + } + + for _, r := range mf.Replace { + err := f.AddReplace(r.Old.Path, r.Old.Version, r.New.Path, r.New.Version) + if err != nil { + return fmt.Errorf("add replace: %v", err) + } + } + f.Cleanup() + return nil +} diff --git a/libgo/go/cmd/go/internal/modconv/convert_test.go b/libgo/go/cmd/go/internal/modconv/convert_test.go new file mode 100644 index 00000000000..ad27abb8ef7 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/convert_test.go @@ -0,0 +1,186 @@ +// 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" + "fmt" + "internal/testenv" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" + + "cmd/go/internal/cfg" + "cmd/go/internal/modfetch" + "cmd/go/internal/modfetch/codehost" + "cmd/go/internal/modfile" + "cmd/go/internal/module" +) + +func TestMain(m *testing.M) { + os.Exit(testMain(m)) +} + +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 := ioutil.TempDir("", "modconv-test-") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(dir) + modfetch.PkgMod = filepath.Join(dir, "pkg/mod") + codehost.WorkRoot = filepath.Join(dir, "codework") + + 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 v0.0.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 v0.0.0-20150131031259-6086d7927ec3 + github.com/docker/docker v0.0.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.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-20150410205453-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.0.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 + )`, + }, + } + + for _, tt := range tests { + t.Run(strings.Replace(tt.path, "/", "_", -1)+"_"+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(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 := ioutil.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/dep.go b/libgo/go/cmd/go/internal/modconv/dep.go new file mode 100644 index 00000000000..690c206a136 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/dep.go @@ -0,0 +1,74 @@ +// 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 ( + "fmt" + "strconv" + "strings" + + "cmd/go/internal/modfile" + "cmd/go/internal/module" + "cmd/go/internal/semver" +) + +func ParseGopkgLock(file string, data []byte) (*modfile.File, error) { + mf := new(modfile.File) + var list []module.Version + var r *module.Version + for lineno, line := range strings.Split(string(data), "\n") { + lineno++ + if i := strings.Index(line, "#"); i >= 0 { + line = line[:i] + } + line = strings.TrimSpace(line) + if line == "[[projects]]" { + list = append(list, module.Version{}) + r = &list[len(list)-1] + continue + } + if strings.HasPrefix(line, "[") { + r = nil + continue + } + if r == nil { + continue + } + i := strings.Index(line, "=") + if i < 0 { + continue + } + key := strings.TrimSpace(line[:i]) + val := strings.TrimSpace(line[i+1:]) + if len(val) >= 2 && val[0] == '"' && val[len(val)-1] == '"' { + q, err := strconv.Unquote(val) // Go unquoting, but close enough for now + if err != nil { + return nil, fmt.Errorf("%s:%d: invalid quoted string: %v", file, lineno, err) + } + val = q + } + switch key { + case "name": + r.Path = val + case "revision", "version": + // Note: key "version" should take priority over "revision", + // and it does, because dep writes toml keys in alphabetical order, + // so we see version (if present) second. + if key == "version" { + if !semver.IsValid(val) || semver.Canonical(val) != val { + break + } + } + r.Version = val + } + } + for _, r := range list { + if r.Path == "" || r.Version == "" { + return nil, fmt.Errorf("%s: empty [[projects]] stanza (%s)", file, r.Path) + } + mf.Require = append(mf.Require, &modfile.Require{Mod: r}) + } + return mf, nil +} diff --git a/libgo/go/cmd/go/internal/modconv/glide.go b/libgo/go/cmd/go/internal/modconv/glide.go new file mode 100644 index 00000000000..3bc675fcc0e --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/glide.go @@ -0,0 +1,42 @@ +// 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 ( + "strings" + + "cmd/go/internal/modfile" + "cmd/go/internal/module" +) + +func ParseGlideLock(file string, data []byte) (*modfile.File, error) { + mf := new(modfile.File) + imports := false + name := "" + for lineno, line := range strings.Split(string(data), "\n") { + lineno++ + if line == "" { + continue + } + if strings.HasPrefix(line, "imports:") { + imports = true + } else if line[0] != '-' && line[0] != ' ' && line[0] != '\t' { + imports = false + } + if !imports { + continue + } + if strings.HasPrefix(line, "- name:") { + name = strings.TrimSpace(line[len("- name:"):]) + } + if strings.HasPrefix(line, " version:") { + version := strings.TrimSpace(line[len(" version:"):]) + if name != "" && version != "" { + mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: name, Version: version}}) + } + } + } + return mf, nil +} diff --git a/libgo/go/cmd/go/internal/modconv/glock.go b/libgo/go/cmd/go/internal/modconv/glock.go new file mode 100644 index 00000000000..1b786a939c7 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/glock.go @@ -0,0 +1,24 @@ +// 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 ( + "strings" + + "cmd/go/internal/modfile" + "cmd/go/internal/module" +) + +func ParseGLOCKFILE(file string, data []byte) (*modfile.File, error) { + mf := new(modfile.File) + for lineno, line := range strings.Split(string(data), "\n") { + lineno++ + f := strings.Fields(line) + if len(f) >= 2 && f[0] != "cmd" { + mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: f[0], Version: f[1]}}) + } + } + return mf, nil +} diff --git a/libgo/go/cmd/go/internal/modconv/godeps.go b/libgo/go/cmd/go/internal/modconv/godeps.go new file mode 100644 index 00000000000..6398dbe7cd7 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/godeps.go @@ -0,0 +1,30 @@ +// 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 ( + "encoding/json" + + "cmd/go/internal/modfile" + "cmd/go/internal/module" +) + +func ParseGodepsJSON(file string, data []byte) (*modfile.File, error) { + var cfg struct { + ImportPath string + Deps []struct { + ImportPath string + Rev string + } + } + if err := json.Unmarshal(data, &cfg); err != nil { + return nil, err + } + mf := new(modfile.File) + for _, d := range cfg.Deps { + mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: d.ImportPath, Version: d.Rev}}) + } + return mf, nil +} diff --git a/libgo/go/cmd/go/internal/modconv/modconv.go b/libgo/go/cmd/go/internal/modconv/modconv.go new file mode 100644 index 00000000000..a58673382e6 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/modconv.go @@ -0,0 +1,19 @@ +// 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 "cmd/go/internal/modfile" + +var Converters = map[string]func(string, []byte) (*modfile.File, error){ + "GLOCKFILE": ParseGLOCKFILE, + "Godeps/Godeps.json": ParseGodepsJSON, + "Gopkg.lock": ParseGopkgLock, + "dependencies.tsv": ParseDependenciesTSV, + "glide.lock": ParseGlideLock, + "vendor.conf": ParseVendorConf, + "vendor.yml": ParseVendorYML, + "vendor/manifest": ParseVendorManifest, + "vendor/vendor.json": ParseVendorJSON, +} diff --git a/libgo/go/cmd/go/internal/modconv/modconv_test.go b/libgo/go/cmd/go/internal/modconv/modconv_test.go new file mode 100644 index 00000000000..353161bc5a3 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/modconv_test.go @@ -0,0 +1,66 @@ +// 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" + "fmt" + "io/ioutil" + "path/filepath" + "testing" +) + +var extMap = map[string]string{ + ".dep": "Gopkg.lock", + ".glide": "glide.lock", + ".glock": "GLOCKFILE", + ".godeps": "Godeps/Godeps.json", + ".tsv": "dependencies.tsv", + ".vconf": "vendor.conf", + ".vjson": "vendor/vendor.json", + ".vyml": "vendor.yml", + ".vmanifest": "vendor/manifest", +} + +func Test(t *testing.T) { + tests, _ := filepath.Glob("testdata/*") + if len(tests) == 0 { + t.Fatalf("no tests found") + } + for _, test := range tests { + file := filepath.Base(test) + ext := filepath.Ext(file) + if ext == ".out" { + continue + } + t.Run(file, func(t *testing.T) { + if extMap[ext] == "" { + t.Fatal("unknown extension") + } + if Converters[extMap[ext]] == nil { + t.Fatalf("Converters[%q] == nil", extMap[ext]) + } + data, err := ioutil.ReadFile(test) + if err != nil { + t.Fatal(err) + } + out, err := Converters[extMap[ext]](test, data) + if err != nil { + t.Fatal(err) + } + want, err := ioutil.ReadFile(test[:len(test)-len(ext)] + ".out") + if err != nil { + t.Error(err) + } + var buf bytes.Buffer + for _, r := range out.Require { + fmt.Fprintf(&buf, "%s %s\n", r.Mod.Path, r.Mod.Version) + } + if !bytes.Equal(buf.Bytes(), want) { + t.Errorf("have:\n%s\nwant:\n%s", buf.Bytes(), want) + } + }) + } +} diff --git a/libgo/go/cmd/go/internal/modconv/testdata/cockroach.glock b/libgo/go/cmd/go/internal/modconv/testdata/cockroach.glock new file mode 100644 index 00000000000..221c8acdfd8 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/cockroach.glock @@ -0,0 +1,41 @@ +cmd github.com/cockroachdb/c-protobuf/cmd/protoc +cmd github.com/cockroachdb/yacc +cmd github.com/gogo/protobuf/protoc-gen-gogo +cmd github.com/golang/lint/golint +cmd github.com/jteeuwen/go-bindata/go-bindata +cmd github.com/kisielk/errcheck +cmd github.com/robfig/glock +cmd github.com/tebeka/go2xunit +cmd golang.org/x/tools/cmd/goimports +cmd golang.org/x/tools/cmd/stringer +github.com/agtorre/gocolorize f42b554bf7f006936130c9bb4f971afd2d87f671 +github.com/biogo/store e1f74b3c58befe661feed7fa4cf52436de753128 +github.com/cockroachdb/c-lz4 6e71f140a365017bbe0904710007f8725fd3f809 +github.com/cockroachdb/c-protobuf 0f9ab7b988ca7474cf76b9a961ab03c0552abcb3 +github.com/cockroachdb/c-rocksdb 7fc876fe79b96de0e25069c9ae27e6444637bd54 +github.com/cockroachdb/c-snappy 618733f9e5bab8463b9049117a335a7a1bfc9fd5 +github.com/cockroachdb/yacc 572e006f8e6b0061ebda949d13744f5108389514 +github.com/coreos/etcd 18ecc297bc913bed6fc093d66b1fa22020dba7dc +github.com/docker/docker 7374852be9def787921aea2ca831771982badecf +github.com/elazarl/go-bindata-assetfs 3dcc96556217539f50599357fb481ac0dc7439b9 +github.com/gogo/protobuf 98e73e511a62a9c232152f94999112c80142a813 +github.com/golang/lint 7b7f4364ff76043e6c3610281525fabc0d90f0e4 +github.com/google/btree cc6329d4279e3f025a53a83c397d2339b5705c45 +github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 +github.com/jteeuwen/go-bindata dce55d09e24ac40a6e725c8420902b86554f8046 +github.com/julienschmidt/httprouter 6aacfd5ab513e34f7e64ea9627ab9670371b34e7 +github.com/kisielk/errcheck 50b84cf7fa18ee2985b8c63ba3de5edd604b9259 +github.com/kisielk/gotool d678387370a2eb9b5b0a33218bc8c9d8de15b6be +github.com/lib/pq a8d8d01c4f91602f876bf5aa210274e8203a6b45 +github.com/montanaflynn/stats 44fb56da2a2a67d394dec0e18a82dd316f192529 +github.com/peterh/liner 1bb0d1c1a25ed393d8feb09bab039b2b1b1fbced +github.com/robfig/glock cb3c3ec56de988289cab7bbd284eddc04dfee6c9 +github.com/samalba/dockerclient 12570e600d71374233e5056ba315f657ced496c7 +github.com/spf13/cobra 66816bcd0378e248c613e3c443c020f544c28804 +github.com/spf13/pflag 67cbc198fd11dab704b214c1e629a97af392c085 +github.com/tebeka/go2xunit d45000af2242dd0e7b8c7b07d82a1068adc5fd40 +golang.org/x/crypto cc04154d65fb9296747569b107cfd05380b1ea3e +golang.org/x/net 8bfde94a845cb31000de3266ac83edbda58dab09 +golang.org/x/text d4cc1b1e16b49d6dafc4982403b40fe89c512cd5 +golang.org/x/tools d02228d1857b9f49cd0252788516ff5584266eb6 +gopkg.in/yaml.v1 9f9df34309c04878acc86042b16630b0f696e1de diff --git a/libgo/go/cmd/go/internal/modconv/testdata/cockroach.out b/libgo/go/cmd/go/internal/modconv/testdata/cockroach.out new file mode 100644 index 00000000000..30cdbb7bf29 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/cockroach.out @@ -0,0 +1,31 @@ +github.com/agtorre/gocolorize f42b554bf7f006936130c9bb4f971afd2d87f671 +github.com/biogo/store e1f74b3c58befe661feed7fa4cf52436de753128 +github.com/cockroachdb/c-lz4 6e71f140a365017bbe0904710007f8725fd3f809 +github.com/cockroachdb/c-protobuf 0f9ab7b988ca7474cf76b9a961ab03c0552abcb3 +github.com/cockroachdb/c-rocksdb 7fc876fe79b96de0e25069c9ae27e6444637bd54 +github.com/cockroachdb/c-snappy 618733f9e5bab8463b9049117a335a7a1bfc9fd5 +github.com/cockroachdb/yacc 572e006f8e6b0061ebda949d13744f5108389514 +github.com/coreos/etcd 18ecc297bc913bed6fc093d66b1fa22020dba7dc +github.com/docker/docker 7374852be9def787921aea2ca831771982badecf +github.com/elazarl/go-bindata-assetfs 3dcc96556217539f50599357fb481ac0dc7439b9 +github.com/gogo/protobuf 98e73e511a62a9c232152f94999112c80142a813 +github.com/golang/lint 7b7f4364ff76043e6c3610281525fabc0d90f0e4 +github.com/google/btree cc6329d4279e3f025a53a83c397d2339b5705c45 +github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 +github.com/jteeuwen/go-bindata dce55d09e24ac40a6e725c8420902b86554f8046 +github.com/julienschmidt/httprouter 6aacfd5ab513e34f7e64ea9627ab9670371b34e7 +github.com/kisielk/errcheck 50b84cf7fa18ee2985b8c63ba3de5edd604b9259 +github.com/kisielk/gotool d678387370a2eb9b5b0a33218bc8c9d8de15b6be +github.com/lib/pq a8d8d01c4f91602f876bf5aa210274e8203a6b45 +github.com/montanaflynn/stats 44fb56da2a2a67d394dec0e18a82dd316f192529 +github.com/peterh/liner 1bb0d1c1a25ed393d8feb09bab039b2b1b1fbced +github.com/robfig/glock cb3c3ec56de988289cab7bbd284eddc04dfee6c9 +github.com/samalba/dockerclient 12570e600d71374233e5056ba315f657ced496c7 +github.com/spf13/cobra 66816bcd0378e248c613e3c443c020f544c28804 +github.com/spf13/pflag 67cbc198fd11dab704b214c1e629a97af392c085 +github.com/tebeka/go2xunit d45000af2242dd0e7b8c7b07d82a1068adc5fd40 +golang.org/x/crypto cc04154d65fb9296747569b107cfd05380b1ea3e +golang.org/x/net 8bfde94a845cb31000de3266ac83edbda58dab09 +golang.org/x/text d4cc1b1e16b49d6dafc4982403b40fe89c512cd5 +golang.org/x/tools d02228d1857b9f49cd0252788516ff5584266eb6 +gopkg.in/yaml.v1 9f9df34309c04878acc86042b16630b0f696e1de diff --git a/libgo/go/cmd/go/internal/modconv/testdata/dockermachine.godeps b/libgo/go/cmd/go/internal/modconv/testdata/dockermachine.godeps new file mode 100644 index 00000000000..a551002a049 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/dockermachine.godeps @@ -0,0 +1,159 @@ +{ + "ImportPath": "github.com/docker/machine", + "GoVersion": "go1.4.2", + "Deps": [ + { + "ImportPath": "code.google.com/p/goauth2/oauth", + "Comment": "weekly-56", + "Rev": "afe77d958c701557ec5dc56f6936fcc194d15520" + }, + { + "ImportPath": "github.com/MSOpenTech/azure-sdk-for-go", + "Comment": "v1.1-17-g515f3ec", + "Rev": "515f3ec74ce6a5b31e934cefae997c97bd0a1b1e" + }, + { + "ImportPath": "github.com/cenkalti/backoff", + "Rev": "9831e1e25c874e0a0601b6dc43641071414eec7a" + }, + { + "ImportPath": "github.com/codegangsta/cli", + "Comment": "1.2.0-64-ge1712f3", + "Rev": "e1712f381785e32046927f64a7c86fe569203196" + }, + { + "ImportPath": "github.com/digitalocean/godo", + "Comment": "v0.5.0", + "Rev": "5478aae80694de1d2d0e02c386bbedd201266234" + }, + { + "ImportPath": "github.com/docker/docker/dockerversion", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/engine", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/archive", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/fileutils", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/ioutils", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/mflag", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/parsers", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/pools", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/promise", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/system", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/term", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/timeutils", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/units", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/pkg/version", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar", + "Comment": "v1.5.0", + "Rev": "a8a31eff10544860d2188dddabdee4d727545796" + }, + { + "ImportPath": "github.com/docker/libtrust", + "Rev": "c54fbb67c1f1e68d7d6f8d2ad7c9360404616a41" + }, + { + "ImportPath": "github.com/google/go-querystring/query", + "Rev": "30f7a39f4a218feb5325f3aebc60c32a572a8274" + }, + { + "ImportPath": "github.com/mitchellh/mapstructure", + "Rev": "740c764bc6149d3f1806231418adb9f52c11bcbf" + }, + { + "ImportPath": "github.com/rackspace/gophercloud", + "Comment": "v1.0.0-558-ce0f487", + "Rev": "ce0f487f6747ab43c4e4404722df25349385bebd" + }, + { + "ImportPath": "github.com/skarademir/naturalsort", + "Rev": "983d4d86054d80f91fd04dd62ec52c1d078ce403" + }, + { + "ImportPath": "github.com/smartystreets/go-aws-auth", + "Rev": "1f0db8c0ee6362470abe06a94e3385927ed72a4b" + }, + { + "ImportPath": "github.com/stretchr/testify/assert", + "Rev": "e4ec8152c15fc46bd5056ce65997a07c7d415325" + }, + { + "ImportPath": "github.com/pyr/egoscale/src/egoscale", + "Rev": "bbaa67324aeeacc90430c1fe0a9c620d3929512e" + }, + { + "ImportPath": "github.com/tent/http-link-go", + "Rev": "ac974c61c2f990f4115b119354b5e0b47550e888" + }, + { + "ImportPath": "github.com/vmware/govcloudair", + "Comment": "v0.0.2", + "Rev": "66a23eaabc61518f91769939ff541886fe1dceef" + }, + { + "ImportPath": "golang.org/x/crypto/ssh", + "Rev": "1fbbd62cfec66bd39d91e97749579579d4d3037e" + }, + { + "ImportPath": "google.golang.org/api/compute/v1", + "Rev": "aa91ac681e18e52b1a0dfe29b9d8354e88c0dcf5" + }, + { + "ImportPath": "google.golang.org/api/googleapi", + "Rev": "aa91ac681e18e52b1a0dfe29b9d8354e88c0dcf5" + } + ] +} diff --git a/libgo/go/cmd/go/internal/modconv/testdata/dockermachine.out b/libgo/go/cmd/go/internal/modconv/testdata/dockermachine.out new file mode 100644 index 00000000000..0b39ceaccbb --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/dockermachine.out @@ -0,0 +1,33 @@ +code.google.com/p/goauth2/oauth afe77d958c701557ec5dc56f6936fcc194d15520 +github.com/MSOpenTech/azure-sdk-for-go 515f3ec74ce6a5b31e934cefae997c97bd0a1b1e +github.com/cenkalti/backoff 9831e1e25c874e0a0601b6dc43641071414eec7a +github.com/codegangsta/cli e1712f381785e32046927f64a7c86fe569203196 +github.com/digitalocean/godo 5478aae80694de1d2d0e02c386bbedd201266234 +github.com/docker/docker/dockerversion a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/engine a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/archive a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/fileutils a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/ioutils a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/mflag a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/parsers a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/pools a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/promise a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/system a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/term a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/timeutils a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/units a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/pkg/version a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar a8a31eff10544860d2188dddabdee4d727545796 +github.com/docker/libtrust c54fbb67c1f1e68d7d6f8d2ad7c9360404616a41 +github.com/google/go-querystring/query 30f7a39f4a218feb5325f3aebc60c32a572a8274 +github.com/mitchellh/mapstructure 740c764bc6149d3f1806231418adb9f52c11bcbf +github.com/rackspace/gophercloud ce0f487f6747ab43c4e4404722df25349385bebd +github.com/skarademir/naturalsort 983d4d86054d80f91fd04dd62ec52c1d078ce403 +github.com/smartystreets/go-aws-auth 1f0db8c0ee6362470abe06a94e3385927ed72a4b +github.com/stretchr/testify/assert e4ec8152c15fc46bd5056ce65997a07c7d415325 +github.com/pyr/egoscale/src/egoscale bbaa67324aeeacc90430c1fe0a9c620d3929512e +github.com/tent/http-link-go ac974c61c2f990f4115b119354b5e0b47550e888 +github.com/vmware/govcloudair 66a23eaabc61518f91769939ff541886fe1dceef +golang.org/x/crypto/ssh 1fbbd62cfec66bd39d91e97749579579d4d3037e +google.golang.org/api/compute/v1 aa91ac681e18e52b1a0dfe29b9d8354e88c0dcf5 +google.golang.org/api/googleapi aa91ac681e18e52b1a0dfe29b9d8354e88c0dcf5 diff --git a/libgo/go/cmd/go/internal/modconv/testdata/dockerman.glide b/libgo/go/cmd/go/internal/modconv/testdata/dockerman.glide new file mode 100644 index 00000000000..5ec765a4c63 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/dockerman.glide @@ -0,0 +1,52 @@ +hash: ead3ea293a6143fe41069ebec814bf197d8c43a92cc7666b1f7e21a419b46feb +updated: 2016-06-20T21:53:35.420817456Z +imports: +- name: github.com/BurntSushi/toml + version: f0aeabca5a127c4078abb8c8d64298b147264b55 +- name: github.com/cpuguy83/go-md2man + version: a65d4d2de4d5f7c74868dfa9b202a3c8be315aaa + subpackages: + - md2man +- name: github.com/fsnotify/fsnotify + version: 30411dbcefb7a1da7e84f75530ad3abe4011b4f8 +- name: github.com/hashicorp/hcl + version: da486364306ed66c218be9b7953e19173447c18b + subpackages: + - hcl/ast + - hcl/parser + - hcl/token + - json/parser + - hcl/scanner + - hcl/strconv + - json/scanner + - json/token +- name: github.com/inconshreveable/mousetrap + version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 +- name: github.com/magiconair/properties + version: c265cfa48dda6474e208715ca93e987829f572f8 +- name: github.com/mitchellh/mapstructure + version: d2dd0262208475919e1a362f675cfc0e7c10e905 +- name: github.com/russross/blackfriday + version: 1d6b8e9301e720b08a8938b8c25c018285885438 +- name: github.com/shurcooL/sanitized_anchor_name + version: 10ef21a441db47d8b13ebcc5fd2310f636973c77 +- name: github.com/spf13/cast + version: 27b586b42e29bec072fe7379259cc719e1289da6 +- name: github.com/spf13/jwalterweatherman + version: 33c24e77fb80341fe7130ee7c594256ff08ccc46 +- name: github.com/spf13/pflag + version: dabebe21bf790f782ea4c7bbd2efc430de182afd +- name: github.com/spf13/viper + version: c1ccc378a054ea8d4e38d8c67f6938d4760b53dd +- name: golang.org/x/sys + version: 62bee037599929a6e9146f29d10dd5208c43507d + subpackages: + - unix +- name: gopkg.in/yaml.v2 + version: a83829b6f1293c91addabc89d0571c246397bbf4 +- name: github.com/spf13/cobra + repo: https://github.com/dnephin/cobra + subpackages: + - doc + version: v1.3 +devImports: [] diff --git a/libgo/go/cmd/go/internal/modconv/testdata/dockerman.out b/libgo/go/cmd/go/internal/modconv/testdata/dockerman.out new file mode 100644 index 00000000000..5e6370b31c3 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/dockerman.out @@ -0,0 +1,16 @@ +github.com/BurntSushi/toml f0aeabca5a127c4078abb8c8d64298b147264b55 +github.com/cpuguy83/go-md2man a65d4d2de4d5f7c74868dfa9b202a3c8be315aaa +github.com/fsnotify/fsnotify 30411dbcefb7a1da7e84f75530ad3abe4011b4f8 +github.com/hashicorp/hcl da486364306ed66c218be9b7953e19173447c18b +github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 +github.com/magiconair/properties c265cfa48dda6474e208715ca93e987829f572f8 +github.com/mitchellh/mapstructure d2dd0262208475919e1a362f675cfc0e7c10e905 +github.com/russross/blackfriday 1d6b8e9301e720b08a8938b8c25c018285885438 +github.com/shurcooL/sanitized_anchor_name 10ef21a441db47d8b13ebcc5fd2310f636973c77 +github.com/spf13/cast 27b586b42e29bec072fe7379259cc719e1289da6 +github.com/spf13/jwalterweatherman 33c24e77fb80341fe7130ee7c594256ff08ccc46 +github.com/spf13/pflag dabebe21bf790f782ea4c7bbd2efc430de182afd +github.com/spf13/viper c1ccc378a054ea8d4e38d8c67f6938d4760b53dd +golang.org/x/sys 62bee037599929a6e9146f29d10dd5208c43507d +gopkg.in/yaml.v2 a83829b6f1293c91addabc89d0571c246397bbf4 +github.com/spf13/cobra v1.3 diff --git a/libgo/go/cmd/go/internal/modconv/testdata/govmomi.out b/libgo/go/cmd/go/internal/modconv/testdata/govmomi.out new file mode 100644 index 00000000000..188c458b3d6 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/govmomi.out @@ -0,0 +1,5 @@ +github.com/davecgh/go-xdr/xdr2 4930550ba2e22f87187498acfd78348b15f4e7a8 +github.com/google/uuid 6a5e28554805e78ea6141142aba763936c4761c0 +github.com/kr/pretty 2ee9d7453c02ef7fa518a83ae23644eb8872186a +github.com/kr/pty 95d05c1eef33a45bd58676b6ce28d105839b8d0b +github.com/vmware/vmw-guestinfo 25eff159a728be87e103a0b8045e08273f4dbec4 diff --git a/libgo/go/cmd/go/internal/modconv/testdata/govmomi.vmanifest b/libgo/go/cmd/go/internal/modconv/testdata/govmomi.vmanifest new file mode 100644 index 00000000000..b89e4ab5eef --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/govmomi.vmanifest @@ -0,0 +1,46 @@ +{ + "version": 0, + "dependencies": [ + { + "importpath": "github.com/davecgh/go-xdr/xdr2", + "repository": "https://github.com/rasky/go-xdr", + "vcs": "git", + "revision": "4930550ba2e22f87187498acfd78348b15f4e7a8", + "branch": "improvements", + "path": "/xdr2", + "notests": true + }, + { + "importpath": "github.com/google/uuid", + "repository": "https://github.com/google/uuid", + "vcs": "git", + "revision": "6a5e28554805e78ea6141142aba763936c4761c0", + "branch": "master", + "notests": true + }, + { + "importpath": "github.com/kr/pretty", + "repository": "https://github.com/dougm/pretty", + "vcs": "git", + "revision": "2ee9d7453c02ef7fa518a83ae23644eb8872186a", + "branch": "govmomi", + "notests": true + }, + { + "importpath": "github.com/kr/pty", + "repository": "https://github.com/kr/pty", + "vcs": "git", + "revision": "95d05c1eef33a45bd58676b6ce28d105839b8d0b", + "branch": "master", + "notests": true + }, + { + "importpath": "github.com/vmware/vmw-guestinfo", + "repository": "https://github.com/vmware/vmw-guestinfo", + "vcs": "git", + "revision": "25eff159a728be87e103a0b8045e08273f4dbec4", + "branch": "master", + "notests": true + } + ] +} diff --git a/libgo/go/cmd/go/internal/modconv/testdata/juju.out b/libgo/go/cmd/go/internal/modconv/testdata/juju.out new file mode 100644 index 00000000000..c2430b1e26d --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/juju.out @@ -0,0 +1,106 @@ +github.com/Azure/azure-sdk-for-go 902d95d9f311ae585ee98cfd18f418b467d60d5a +github.com/Azure/go-autorest 6f40a8acfe03270d792cb8155e2942c09d7cff95 +github.com/ajstarks/svgo 89e3ac64b5b3e403a5e7c35ea4f98d45db7b4518 +github.com/altoros/gosigma 31228935eec685587914528585da4eb9b073c76d +github.com/beorn7/perks 3ac7bf7a47d159a033b107610db8a1b6575507a4 +github.com/bmizerany/pat c068ca2f0aacee5ac3681d68e4d0a003b7d1fd2c +github.com/coreos/go-systemd 7b2428fec40033549c68f54e26e89e7ca9a9ce31 +github.com/dgrijalva/jwt-go 01aeca54ebda6e0fbfafd0a524d234159c05ec20 +github.com/dustin/go-humanize 145fabdb1ab757076a70a886d092a3af27f66f4c +github.com/godbus/dbus 32c6cc29c14570de4cf6d7e7737d68fb2d01ad15 +github.com/golang/protobuf 4bd1920723d7b7c925de087aa32e2187708897f7 +github.com/google/go-querystring 9235644dd9e52eeae6fa48efd539fdc351a0af53 +github.com/gorilla/schema 08023a0215e7fc27a9aecd8b8c50913c40019478 +github.com/gorilla/websocket 804cb600d06b10672f2fbc0a336a7bee507a428e +github.com/gosuri/uitable 36ee7e946282a3fb1cfecd476ddc9b35d8847e42 +github.com/joyent/gocommon ade826b8b54e81a779ccb29d358a45ba24b7809c +github.com/joyent/gosdc 2f11feadd2d9891e92296a1077c3e2e56939547d +github.com/joyent/gosign 0da0d5f1342065321c97812b1f4ac0c2b0bab56c +github.com/juju/ansiterm b99631de12cf04a906c1d4e4ec54fb86eae5863d +github.com/juju/blobstore 06056004b3d7b54bbb7984d830c537bad00fec21 +github.com/juju/bundlechanges 7725027b95e0d54635e0fb11efc2debdcdf19f75 +github.com/juju/cmd 9425a576247f348b9b40afe3b60085de63470de5 +github.com/juju/description d3742c23561884cd7d759ef7142340af1d22cab0 +github.com/juju/errors 1b5e39b83d1835fa480e0c2ddefb040ee82d58b3 +github.com/juju/gnuflag 4e76c56581859c14d9d87e1ddbe29e1c0f10195f +github.com/juju/go4 40d72ab9641a2a8c36a9c46a51e28367115c8e59 +github.com/juju/gojsonpointer afe8b77aa08f272b49e01b82de78510c11f61500 +github.com/juju/gojsonreference f0d24ac5ee330baa21721cdff56d45e4ee42628e +github.com/juju/gojsonschema e1ad140384f254c82f89450d9a7c8dd38a632838 +github.com/juju/gomaasapi cfbc096bd45f276c17a391efc4db710b60ae3ad7 +github.com/juju/httpprof 14bf14c307672fd2456bdbf35d19cf0ccd3cf565 +github.com/juju/httprequest 266fd1e9debf09c037a63f074d099a2da4559ece +github.com/juju/idmclient 4dc25171f675da4206b71695d3fd80e519ad05c1 +github.com/juju/jsonschema a0ef8b74ebcffeeff9fc374854deb4af388f037e +github.com/juju/loggo 21bc4c63e8b435779a080e39e592969b7b90b889 +github.com/juju/mempool 24974d6c264fe5a29716e7d56ea24c4bd904b7cc +github.com/juju/mutex 59c26ee163447c5c57f63ff71610d433862013de +github.com/juju/persistent-cookiejar 5243747bf8f2d0897f6c7a52799327dc97d585e8 +github.com/juju/pubsub 9dcaca7eb4340dbf685aa7b3ad4cc4f8691a33d4 +github.com/juju/replicaset 6b5becf2232ce76656ea765d8d915d41755a1513 +github.com/juju/retry 62c62032529169c7ec02fa48f93349604c345e1f +github.com/juju/rfc ebdbbdb950cd039a531d15cdc2ac2cbd94f068ee +github.com/juju/romulus 98d6700423d63971f10ca14afea9ecf2b9b99f0f +github.com/juju/schema 075de04f9b7d7580d60a1e12a0b3f50bb18e6998 +github.com/juju/terms-client 9b925afd677234e4146dde3cb1a11e187cbed64e +github.com/juju/testing fce9bc4ebf7a77310c262ac4884e03b778eae06a +github.com/juju/txn 28898197906200d603394d8e4ce537436529f1c5 +github.com/juju/usso 68a59c96c178fbbad65926e7f93db50a2cd14f33 +github.com/juju/utils 9f8aeb9b09e2d8c769be8317ccfa23f7eec62c26 +github.com/juju/version 1f41e27e54f21acccf9b2dddae063a782a8a7ceb +github.com/juju/webbrowser 54b8c57083b4afb7dc75da7f13e2967b2606a507 +github.com/juju/xml eb759a627588d35166bc505fceb51b88500e291e +github.com/juju/zip f6b1e93fa2e29a1d7d49b566b2b51efb060c982a +github.com/julienschmidt/httprouter 77a895ad01ebc98a4dc95d8355bc825ce80a56f6 +github.com/lestrrat/go-jspointer f4881e611bdbe9fb413a7780721ef8400a1f2341 +github.com/lestrrat/go-jsref e452c7b5801d1c6494c9e7e0cbc7498c0f88dfd1 +github.com/lestrrat/go-jsschema b09d7650b822d2ea3dc83d5091a5e2acd8330051 +github.com/lestrrat/go-jsval b1258a10419fe0693f7b35ad65cd5074bc0ba1e5 +github.com/lestrrat/go-pdebug 2e6eaaa5717f81bda41d27070d3c966f40a1e75f +github.com/lestrrat/go-structinfo f74c056fe41f860aa6264478c664a6fff8a64298 +github.com/lunixbochs/vtclean 4fbf7632a2c6d3fbdb9931439bdbbeded02cbe36 +github.com/lxc/lxd 23da0234979fa6299565b91b529a6dbeb42ee36d +github.com/masterzen/azure-sdk-for-go ee4f0065d00cd12b542f18f5bc45799e88163b12 +github.com/masterzen/simplexml 4572e39b1ab9fe03ee513ce6fc7e289e98482190 +github.com/masterzen/winrm 7a535cd943fccaeed196718896beec3fb51aff41 +github.com/masterzen/xmlpath 13f4951698adc0fa9c1dda3e275d489a24201161 +github.com/mattn/go-colorable ed8eb9e318d7a84ce5915b495b7d35e0cfe7b5a8 +github.com/mattn/go-isatty 66b8e73f3f5cda9f96b69efd03dd3d7fc4a5cdb8 +github.com/mattn/go-runewidth d96d1bd051f2bd9e7e43d602782b37b93b1b5666 +github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c +github.com/nu7hatch/gouuid 179d4d0c4d8d407a32af483c2354df1d2c91e6c3 +github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9 +github.com/prometheus/client_golang 575f371f7862609249a1be4c9145f429fe065e32 +github.com/prometheus/client_model fa8ad6fec33561be4280a8f0514318c79d7f6cb6 +github.com/prometheus/common dd586c1c5abb0be59e60f942c22af711a2008cb4 +github.com/prometheus/procfs abf152e5f3e97f2fafac028d2cc06c1feb87ffa5 +github.com/rogpeppe/fastuuid 6724a57986aff9bff1a1770e9347036def7c89f6 +github.com/vmware/govmomi c0c7ce63df7edd78e713257b924c89d9a2dac119 +golang.org/x/crypto 8e06e8ddd9629eb88639aba897641bff8031f1d3 +golang.org/x/net ea47fc708ee3e20177f3ca3716217c4ab75942cb +golang.org/x/oauth2 11c60b6f71a6ad48ed6f93c65fa4c6f9b1b5b46a +golang.org/x/sys 7a6e5648d140666db5d920909e082ca00a87ba2c +golang.org/x/text 2910a502d2bf9e43193af9d68ca516529614eed3 +google.golang.org/api 0d3983fb069cb6651353fc44c5cb604e263f2a93 +google.golang.org/cloud f20d6dcccb44ed49de45ae3703312cb46e627db1 +gopkg.in/amz.v3 8c3190dff075bf5442c9eedbf8f8ed6144a099e7 +gopkg.in/check.v1 4f90aeace3a26ad7021961c297b22c42160c7b25 +gopkg.in/errgo.v1 442357a80af5c6bf9b6d51ae791a39c3421004f3 +gopkg.in/goose.v1 ac43167b647feacdd9a1e34ee81e574551bc748d +gopkg.in/ini.v1 776aa739ce9373377cd16f526cdf06cb4c89b40f +gopkg.in/juju/blobstore.v2 51fa6e26128d74e445c72d3a91af555151cc3654 +gopkg.in/juju/charm.v6-unstable 83771c4919d6810bce5b7e63f46bea5fbfed0b93 +gopkg.in/juju/charmrepo.v2-unstable e79aa298df89ea887c9bffec46063c24bfb730f7 +gopkg.in/juju/charmstore.v5-unstable fd1eef3002fc6b6daff5e97efab6f5056d22dcc7 +gopkg.in/juju/environschema.v1 7359fc7857abe2b11b5b3e23811a9c64cb6b01e0 +gopkg.in/juju/jujusvg.v2 d82160011935ef79fc7aca84aba2c6f74700fe75 +gopkg.in/juju/names.v2 0847c26d322a121e52614f969fb82eae2820c715 +gopkg.in/juju/worker.v1 6965b9d826717287bb002e02d1fd4d079978083e +gopkg.in/macaroon-bakery.v1 469b44e6f1f9479e115c8ae879ef80695be624d5 +gopkg.in/macaroon.v1 ab3940c6c16510a850e1c2dd628b919f0f3f1464 +gopkg.in/mgo.v2 f2b6f6c918c452ad107eec89615f074e3bd80e33 +gopkg.in/natefinch/lumberjack.v2 514cbda263a734ae8caac038dadf05f8f3f9f738 +gopkg.in/natefinch/npipe.v2 c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6 +gopkg.in/retry.v1 c09f6b86ba4d5d2cf5bdf0665364aec9fd4815db +gopkg.in/tomb.v1 dd632973f1e7218eb1089048e0798ec9ae7dceb8 +gopkg.in/yaml.v2 a3f3340b5840cee44f372bddb5880fcbc419b46a diff --git a/libgo/go/cmd/go/internal/modconv/testdata/juju.tsv b/libgo/go/cmd/go/internal/modconv/testdata/juju.tsv new file mode 100644 index 00000000000..0bddcef81ce --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/juju.tsv @@ -0,0 +1,106 @@ +github.com/Azure/azure-sdk-for-go git 902d95d9f311ae585ee98cfd18f418b467d60d5a 2016-07-20T05:16:58Z +github.com/Azure/go-autorest git 6f40a8acfe03270d792cb8155e2942c09d7cff95 2016-07-19T23:14:56Z +github.com/ajstarks/svgo git 89e3ac64b5b3e403a5e7c35ea4f98d45db7b4518 2014-10-04T21:11:59Z +github.com/altoros/gosigma git 31228935eec685587914528585da4eb9b073c76d 2015-04-08T14:52:32Z +github.com/beorn7/perks git 3ac7bf7a47d159a033b107610db8a1b6575507a4 2016-02-29T21:34:45Z +github.com/bmizerany/pat git c068ca2f0aacee5ac3681d68e4d0a003b7d1fd2c 2016-02-17T10:32:42Z +github.com/coreos/go-systemd git 7b2428fec40033549c68f54e26e89e7ca9a9ce31 2016-02-02T21:14:25Z +github.com/dgrijalva/jwt-go git 01aeca54ebda6e0fbfafd0a524d234159c05ec20 2016-07-05T20:30:06Z +github.com/dustin/go-humanize git 145fabdb1ab757076a70a886d092a3af27f66f4c 2014-12-28T07:11:48Z +github.com/godbus/dbus git 32c6cc29c14570de4cf6d7e7737d68fb2d01ad15 2016-05-06T22:25:50Z +github.com/golang/protobuf git 4bd1920723d7b7c925de087aa32e2187708897f7 2016-11-09T07:27:36Z +github.com/google/go-querystring git 9235644dd9e52eeae6fa48efd539fdc351a0af53 2016-04-01T23:30:42Z +github.com/gorilla/schema git 08023a0215e7fc27a9aecd8b8c50913c40019478 2016-04-26T23:15:12Z +github.com/gorilla/websocket git 804cb600d06b10672f2fbc0a336a7bee507a428e 2017-02-14T17:41:18Z +github.com/gosuri/uitable git 36ee7e946282a3fb1cfecd476ddc9b35d8847e42 2016-04-04T20:39:58Z +github.com/joyent/gocommon git ade826b8b54e81a779ccb29d358a45ba24b7809c 2016-03-20T19:31:33Z +github.com/joyent/gosdc git 2f11feadd2d9891e92296a1077c3e2e56939547d 2014-05-24T00:08:15Z +github.com/joyent/gosign git 0da0d5f1342065321c97812b1f4ac0c2b0bab56c 2014-05-24T00:07:34Z +github.com/juju/ansiterm git b99631de12cf04a906c1d4e4ec54fb86eae5863d 2016-09-07T23:45:32Z +github.com/juju/blobstore git 06056004b3d7b54bbb7984d830c537bad00fec21 2015-07-29T11:18:58Z +github.com/juju/bundlechanges git 7725027b95e0d54635e0fb11efc2debdcdf19f75 2016-12-15T16:06:52Z +github.com/juju/cmd git 9425a576247f348b9b40afe3b60085de63470de5 2017-03-20T01:37:09Z +github.com/juju/description git d3742c23561884cd7d759ef7142340af1d22cab0 2017-03-20T07:46:40Z +github.com/juju/errors git 1b5e39b83d1835fa480e0c2ddefb040ee82d58b3 2015-09-16T12:56:42Z +github.com/juju/gnuflag git 4e76c56581859c14d9d87e1ddbe29e1c0f10195f 2016-08-09T16:52:14Z +github.com/juju/go4 git 40d72ab9641a2a8c36a9c46a51e28367115c8e59 2016-02-22T16:32:58Z +github.com/juju/gojsonpointer git afe8b77aa08f272b49e01b82de78510c11f61500 2015-02-04T19:46:29Z +github.com/juju/gojsonreference git f0d24ac5ee330baa21721cdff56d45e4ee42628e 2015-02-04T19:46:33Z +github.com/juju/gojsonschema git e1ad140384f254c82f89450d9a7c8dd38a632838 2015-03-12T17:00:16Z +github.com/juju/gomaasapi git cfbc096bd45f276c17a391efc4db710b60ae3ad7 2017-02-27T07:51:07Z +github.com/juju/httpprof git 14bf14c307672fd2456bdbf35d19cf0ccd3cf565 2014-12-17T16:00:36Z +github.com/juju/httprequest git 266fd1e9debf09c037a63f074d099a2da4559ece 2016-10-06T15:09:09Z +github.com/juju/idmclient git 4dc25171f675da4206b71695d3fd80e519ad05c1 2017-02-09T16:27:49Z +github.com/juju/jsonschema git a0ef8b74ebcffeeff9fc374854deb4af388f037e 2016-11-02T18:19:19Z +github.com/juju/loggo git 21bc4c63e8b435779a080e39e592969b7b90b889 2017-02-22T12:20:47Z +github.com/juju/mempool git 24974d6c264fe5a29716e7d56ea24c4bd904b7cc 2016-02-05T10:49:27Z +github.com/juju/mutex git 59c26ee163447c5c57f63ff71610d433862013de 2016-06-17T01:09:07Z +github.com/juju/persistent-cookiejar git 5243747bf8f2d0897f6c7a52799327dc97d585e8 2016-11-15T13:33:28Z +github.com/juju/pubsub git 9dcaca7eb4340dbf685aa7b3ad4cc4f8691a33d4 2016-07-28T03:00:34Z +github.com/juju/replicaset git 6b5becf2232ce76656ea765d8d915d41755a1513 2016-11-25T16:08:49Z +github.com/juju/retry git 62c62032529169c7ec02fa48f93349604c345e1f 2015-10-29T02:48:21Z +github.com/juju/rfc git ebdbbdb950cd039a531d15cdc2ac2cbd94f068ee 2016-07-11T02:42:13Z +github.com/juju/romulus git 98d6700423d63971f10ca14afea9ecf2b9b99f0f 2017-01-23T14:29:29Z +github.com/juju/schema git 075de04f9b7d7580d60a1e12a0b3f50bb18e6998 2016-04-20T04:42:03Z +github.com/juju/terms-client git 9b925afd677234e4146dde3cb1a11e187cbed64e 2016-08-09T13:19:00Z +github.com/juju/testing git fce9bc4ebf7a77310c262ac4884e03b778eae06a 2017-02-22T09:01:19Z +github.com/juju/txn git 28898197906200d603394d8e4ce537436529f1c5 2016-11-16T04:07:55Z +github.com/juju/usso git 68a59c96c178fbbad65926e7f93db50a2cd14f33 2016-04-01T10:44:24Z +github.com/juju/utils git 9f8aeb9b09e2d8c769be8317ccfa23f7eec62c26 2017-02-15T08:19:00Z +github.com/juju/version git 1f41e27e54f21acccf9b2dddae063a782a8a7ceb 2016-10-31T05:19:06Z +github.com/juju/webbrowser git 54b8c57083b4afb7dc75da7f13e2967b2606a507 2016-03-09T14:36:29Z +github.com/juju/xml git eb759a627588d35166bc505fceb51b88500e291e 2015-04-13T13:11:21Z +github.com/juju/zip git f6b1e93fa2e29a1d7d49b566b2b51efb060c982a 2016-02-05T10:52:21Z +github.com/julienschmidt/httprouter git 77a895ad01ebc98a4dc95d8355bc825ce80a56f6 2015-10-13T22:55:20Z +github.com/lestrrat/go-jspointer git f4881e611bdbe9fb413a7780721ef8400a1f2341 2016-02-29T02:13:54Z +github.com/lestrrat/go-jsref git e452c7b5801d1c6494c9e7e0cbc7498c0f88dfd1 2016-06-01T01:32:40Z +github.com/lestrrat/go-jsschema git b09d7650b822d2ea3dc83d5091a5e2acd8330051 2016-09-03T13:19:57Z +github.com/lestrrat/go-jsval git b1258a10419fe0693f7b35ad65cd5074bc0ba1e5 2016-10-12T04:57:17Z +github.com/lestrrat/go-pdebug git 2e6eaaa5717f81bda41d27070d3c966f40a1e75f 2016-08-17T06:33:33Z +github.com/lestrrat/go-structinfo git f74c056fe41f860aa6264478c664a6fff8a64298 2016-03-08T13:11:05Z +github.com/lunixbochs/vtclean git 4fbf7632a2c6d3fbdb9931439bdbbeded02cbe36 2016-01-25T03:51:06Z +github.com/lxc/lxd git 23da0234979fa6299565b91b529a6dbeb42ee36d 2017-02-16T05:29:42Z +github.com/masterzen/azure-sdk-for-go git ee4f0065d00cd12b542f18f5bc45799e88163b12 2016-10-14T13:56:28Z +github.com/masterzen/simplexml git 4572e39b1ab9fe03ee513ce6fc7e289e98482190 2016-06-08T18:30:07Z +github.com/masterzen/winrm git 7a535cd943fccaeed196718896beec3fb51aff41 2016-10-14T15:10:40Z +github.com/masterzen/xmlpath git 13f4951698adc0fa9c1dda3e275d489a24201161 2014-02-18T18:59:01Z +github.com/mattn/go-colorable git ed8eb9e318d7a84ce5915b495b7d35e0cfe7b5a8 2016-07-31T23:54:17Z +github.com/mattn/go-isatty git 66b8e73f3f5cda9f96b69efd03dd3d7fc4a5cdb8 2016-08-06T12:27:52Z +github.com/mattn/go-runewidth git d96d1bd051f2bd9e7e43d602782b37b93b1b5666 2015-11-18T07:21:59Z +github.com/matttproud/golang_protobuf_extensions git c12348ce28de40eed0136aa2b644d0ee0650e56c 2016-04-24T11:30:07Z +github.com/nu7hatch/gouuid git 179d4d0c4d8d407a32af483c2354df1d2c91e6c3 2013-12-21T20:05:32Z +github.com/pkg/errors git 839d9e913e063e28dfd0e6c7b7512793e0a48be9 2016-10-02T05:25:12Z +github.com/prometheus/client_golang git 575f371f7862609249a1be4c9145f429fe065e32 2016-11-24T15:57:32Z +github.com/prometheus/client_model git fa8ad6fec33561be4280a8f0514318c79d7f6cb6 2015-02-12T10:17:44Z +github.com/prometheus/common git dd586c1c5abb0be59e60f942c22af711a2008cb4 2016-05-03T22:05:32Z +github.com/prometheus/procfs git abf152e5f3e97f2fafac028d2cc06c1feb87ffa5 2016-04-11T19:08:41Z +github.com/rogpeppe/fastuuid git 6724a57986aff9bff1a1770e9347036def7c89f6 2015-01-06T09:32:20Z +github.com/vmware/govmomi git c0c7ce63df7edd78e713257b924c89d9a2dac119 2016-06-30T15:37:42Z +golang.org/x/crypto git 8e06e8ddd9629eb88639aba897641bff8031f1d3 2016-09-22T17:06:29Z +golang.org/x/net git ea47fc708ee3e20177f3ca3716217c4ab75942cb 2015-08-29T23:03:18Z +golang.org/x/oauth2 git 11c60b6f71a6ad48ed6f93c65fa4c6f9b1b5b46a 2015-03-25T02:00:22Z +golang.org/x/sys git 7a6e5648d140666db5d920909e082ca00a87ba2c 2017-02-01T05:12:45Z +golang.org/x/text git 2910a502d2bf9e43193af9d68ca516529614eed3 2016-07-26T16:48:57Z +google.golang.org/api git 0d3983fb069cb6651353fc44c5cb604e263f2a93 2014-12-10T23:51:26Z +google.golang.org/cloud git f20d6dcccb44ed49de45ae3703312cb46e627db1 2015-03-19T22:36:35Z +gopkg.in/amz.v3 git 8c3190dff075bf5442c9eedbf8f8ed6144a099e7 2016-12-15T13:08:49Z +gopkg.in/check.v1 git 4f90aeace3a26ad7021961c297b22c42160c7b25 2016-01-05T16:49:36Z +gopkg.in/errgo.v1 git 442357a80af5c6bf9b6d51ae791a39c3421004f3 2016-12-22T12:58:16Z +gopkg.in/goose.v1 git ac43167b647feacdd9a1e34ee81e574551bc748d 2017-02-15T01:56:23Z +gopkg.in/ini.v1 git 776aa739ce9373377cd16f526cdf06cb4c89b40f 2016-02-22T23:24:41Z +gopkg.in/juju/blobstore.v2 git 51fa6e26128d74e445c72d3a91af555151cc3654 2016-01-25T02:37:03Z +gopkg.in/juju/charm.v6-unstable git 83771c4919d6810bce5b7e63f46bea5fbfed0b93 2016-10-03T20:31:18Z +gopkg.in/juju/charmrepo.v2-unstable git e79aa298df89ea887c9bffec46063c24bfb730f7 2016-11-17T15:25:28Z +gopkg.in/juju/charmstore.v5-unstable git fd1eef3002fc6b6daff5e97efab6f5056d22dcc7 2016-09-16T10:09:07Z +gopkg.in/juju/environschema.v1 git 7359fc7857abe2b11b5b3e23811a9c64cb6b01e0 2015-11-04T11:58:10Z +gopkg.in/juju/jujusvg.v2 git d82160011935ef79fc7aca84aba2c6f74700fe75 2016-06-09T10:52:15Z +gopkg.in/juju/names.v2 git 0847c26d322a121e52614f969fb82eae2820c715 2016-11-02T13:43:03Z +gopkg.in/juju/worker.v1 git 6965b9d826717287bb002e02d1fd4d079978083e 2017-03-08T00:24:58Z +gopkg.in/macaroon-bakery.v1 git 469b44e6f1f9479e115c8ae879ef80695be624d5 2016-06-22T12:14:21Z +gopkg.in/macaroon.v1 git ab3940c6c16510a850e1c2dd628b919f0f3f1464 2015-01-21T11:42:31Z +gopkg.in/mgo.v2 git f2b6f6c918c452ad107eec89615f074e3bd80e33 2016-08-18T01:52:18Z +gopkg.in/natefinch/lumberjack.v2 git 514cbda263a734ae8caac038dadf05f8f3f9f738 2016-01-25T11:17:49Z +gopkg.in/natefinch/npipe.v2 git c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6 2016-06-21T03:49:01Z +gopkg.in/retry.v1 git c09f6b86ba4d5d2cf5bdf0665364aec9fd4815db 2016-10-25T18:14:30Z +gopkg.in/tomb.v1 git dd632973f1e7218eb1089048e0798ec9ae7dceb8 2014-10-24T13:56:13Z +gopkg.in/yaml.v2 git a3f3340b5840cee44f372bddb5880fcbc419b46a 2017-02-08T14:18:51Z diff --git a/libgo/go/cmd/go/internal/modconv/testdata/moby.out b/libgo/go/cmd/go/internal/modconv/testdata/moby.out new file mode 100644 index 00000000000..2cb2e056a83 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/moby.out @@ -0,0 +1,105 @@ +github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109 +github.com/Microsoft/hcsshim v0.6.5 +github.com/Microsoft/go-winio v0.4.5 +github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76 +github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a +github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 +github.com/gorilla/context v1.1 +github.com/gorilla/mux v1.1 +github.com/Microsoft/opengcs v0.3.4 +github.com/kr/pty 5cf931ef8f +github.com/mattn/go-shellwords v1.0.3 +github.com/sirupsen/logrus v1.0.3 +github.com/tchap/go-patricia v2.2.6 +github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 +golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6 +golang.org/x/sys 07c182904dbd53199946ba614a412c61d3c548f5 +github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1 +github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d +golang.org/x/text f72d8390a633d5dfb0cc84043294db9f6c935756 +github.com/stretchr/testify 4d4bfba8f1d1027c4fdbe371823030df51419987 +github.com/pmezard/go-difflib v1.0.0 +github.com/gotestyourself/gotestyourself v1.1.0 +github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 +github.com/imdario/mergo 0.2.1 +golang.org/x/sync de49d9dcd27d4f764488181bea099dfe6179bcf0 +github.com/containerd/continuity 22694c680ee48fb8f50015b44618517e2bde77e8 +github.com/moby/buildkit aaff9d591ef128560018433fe61beb802e149de8 +github.com/tonistiigi/fsutil dea3a0da73aee887fc02142d995be764106ac5e2 +github.com/docker/libnetwork 68f1039f172434709a4550fe92e3e058406c74ce +github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 +github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 +github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec +github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b +github.com/hashicorp/memberlist v0.1.0 +github.com/sean-/seed e2103e2c35297fb7e17febb81e49b312087a2372 +github.com/hashicorp/go-sockaddr acd314c5781ea706c710d9ea70069fd2e110d61d +github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e +github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870 +github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef +github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25 +github.com/vishvananda/netlink bd6d5de5ccef2d66b0a26177928d0d8895d7f969 +github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060 +github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374 +github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d +github.com/coreos/etcd v3.2.1 +github.com/coreos/go-semver v0.2.0 +github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065 +github.com/hashicorp/consul v0.5.2 +github.com/boltdb/bolt fff57c100f4dea1905678da7e90d92429dff2904 +github.com/miekg/dns 75e6e86cc601825c5dbcd4e0c209eab180997cd7 +github.com/docker/distribution edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c +github.com/vbatts/tar-split v0.10.1 +github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb +github.com/mistifyio/go-zfs 22c9b32c84eb0d0c6f4043b6e90fc94073de92fa +github.com/pborman/uuid v1.0 +google.golang.org/grpc v1.3.0 +github.com/opencontainers/runc 0351df1c5a66838d0c392b4ac4cf9450de844e2d +github.com/opencontainers/image-spec 372ad780f63454fbbbbcc7cf80e5b90245c13e13 +github.com/opencontainers/runtime-spec v1.0.0 +github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0 +github.com/coreos/go-systemd v4 +github.com/godbus/dbus v4.0.0 +github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852 +github.com/golang/protobuf 7a211bcf3bce0e3f1d74f9894916e6f116ae83b4 +github.com/Graylog2/go-gelf v2 +github.com/fluent/fluent-logger-golang v1.2.1 +github.com/philhofer/fwd 98c11a7a6ec829d672b03833c3d69a7fae1ca972 +github.com/tinylib/msgp 75ee40d2601edf122ef667e2a07d600d4c44490c +github.com/fsnotify/fsnotify v1.4.2 +github.com/aws/aws-sdk-go v1.4.22 +github.com/go-ini/ini 060d7da055ba6ec5ea7a31f116332fe5efa04ce0 +github.com/jmespath/go-jmespath 0b12d6b521d83fc7f755e7cfc1b1fbdd35a01a74 +github.com/bsphere/le_go 7a984a84b5492ae539b79b62fb4a10afc63c7bcf +golang.org/x/oauth2 96382aa079b72d8c014eb0c50f6c223d1e6a2de0 +google.golang.org/api 3cc2e591b550923a2c5f0ab5a803feda924d5823 +cloud.google.com/go 9d965e63e8cceb1b5d7977a202f0fcb8866d6525 +github.com/googleapis/gax-go da06d194a00e19ce00d9011a13931c3f6f6887c7 +google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 +github.com/containerd/containerd 06b9cb35161009dcb7123345749fef02f7cea8e0 +github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4 +github.com/docker/swarmkit 872861d2ae46958af7ead1d5fffb092c73afbaf0 +github.com/gogo/protobuf v0.4 +github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a +github.com/google/certificate-transparency d90e65c3a07988180c5b1ece71791c0b6506826e +golang.org/x/crypto 558b6879de74bc843225cde5686419267ff707ca +golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb +github.com/hashicorp/go-memdb cb9a474f84cc5e41b273b20c6927680b2a8776ad +github.com/hashicorp/go-immutable-radix 8e8ed81f8f0bf1bdd829593fdd5c29922c1ea990 +github.com/hashicorp/golang-lru a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4 +github.com/coreos/pkg fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8 +github.com/pivotal-golang/clock 3fd3c1944c59d9742e1cd333672181cd1a6f9fa0 +github.com/prometheus/client_golang 52437c81da6b127a9925d17eb3a382a2e5fd395e +github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 +github.com/prometheus/client_model fa8ad6fec33561be4280a8f0514318c79d7f6cb6 +github.com/prometheus/common ebdfc6da46522d58825777cf1f90490a5b1ef1d8 +github.com/prometheus/procfs abf152e5f3e97f2fafac028d2cc06c1feb87ffa5 +github.com/matttproud/golang_protobuf_extensions v1.0.0 +github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9 +github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0 +github.com/spf13/cobra v1.5.1 +github.com/spf13/pflag 9ff6c6923cfffbcd502984b8e0c80539a94968b7 +github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 +github.com/Nvveen/Gotty a8b993ba6abdb0e0c12b0125c603323a71c7790c +github.com/docker/go-metrics d466d4f6fd960e01820085bd7e1a24426ee7ef18 +github.com/opencontainers/selinux v1.0.0-rc1 diff --git a/libgo/go/cmd/go/internal/modconv/testdata/moby.vconf b/libgo/go/cmd/go/internal/modconv/testdata/moby.vconf new file mode 100644 index 00000000000..53b90d1e372 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/moby.vconf @@ -0,0 +1,149 @@ +# the following lines are in sorted order, FYI +github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109 +github.com/Microsoft/hcsshim v0.6.5 +github.com/Microsoft/go-winio v0.4.5 +github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76 +github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a +github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git +github.com/gorilla/context v1.1 +github.com/gorilla/mux v1.1 +github.com/Microsoft/opengcs v0.3.4 +github.com/kr/pty 5cf931ef8f +github.com/mattn/go-shellwords v1.0.3 +github.com/sirupsen/logrus v1.0.3 +github.com/tchap/go-patricia v2.2.6 +github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 +golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6 +golang.org/x/sys 07c182904dbd53199946ba614a412c61d3c548f5 +github.com/docker/go-units 9e638d38cf6977a37a8ea0078f3ee75a7cdb2dd1 +github.com/docker/go-connections 3ede32e2033de7505e6500d6c868c2b9ed9f169d +golang.org/x/text f72d8390a633d5dfb0cc84043294db9f6c935756 +github.com/stretchr/testify 4d4bfba8f1d1027c4fdbe371823030df51419987 +github.com/pmezard/go-difflib v1.0.0 +github.com/gotestyourself/gotestyourself v1.1.0 + +github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 +github.com/imdario/mergo 0.2.1 +golang.org/x/sync de49d9dcd27d4f764488181bea099dfe6179bcf0 + +github.com/containerd/continuity 22694c680ee48fb8f50015b44618517e2bde77e8 +github.com/moby/buildkit aaff9d591ef128560018433fe61beb802e149de8 +github.com/tonistiigi/fsutil dea3a0da73aee887fc02142d995be764106ac5e2 + +#get libnetwork packages +github.com/docker/libnetwork 68f1039f172434709a4550fe92e3e058406c74ce +github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9 +github.com/armon/go-radix e39d623f12e8e41c7b5529e9a9dd67a1e2261f80 +github.com/armon/go-metrics eb0af217e5e9747e41dd5303755356b62d28e3ec +github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b +github.com/hashicorp/memberlist v0.1.0 +github.com/sean-/seed e2103e2c35297fb7e17febb81e49b312087a2372 +github.com/hashicorp/go-sockaddr acd314c5781ea706c710d9ea70069fd2e110d61d +github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e +github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870 +github.com/docker/libkv 1d8431073ae03cdaedb198a89722f3aab6d418ef +github.com/vishvananda/netns 604eaf189ee867d8c147fafc28def2394e878d25 +github.com/vishvananda/netlink bd6d5de5ccef2d66b0a26177928d0d8895d7f969 +github.com/BurntSushi/toml f706d00e3de6abe700c994cdd545a1a4915af060 +github.com/samuel/go-zookeeper d0e0d8e11f318e000a8cc434616d69e329edc374 +github.com/deckarep/golang-set ef32fa3046d9f249d399f98ebaf9be944430fd1d +github.com/coreos/etcd v3.2.1 +github.com/coreos/go-semver v0.2.0 +github.com/ugorji/go f1f1a805ed361a0e078bb537e4ea78cd37dcf065 +github.com/hashicorp/consul v0.5.2 +github.com/boltdb/bolt fff57c100f4dea1905678da7e90d92429dff2904 +github.com/miekg/dns 75e6e86cc601825c5dbcd4e0c209eab180997cd7 + +# get graph and distribution packages +github.com/docker/distribution edc3ab29cdff8694dd6feb85cfeb4b5f1b38ed9c +github.com/vbatts/tar-split v0.10.1 +github.com/opencontainers/go-digest a6d0ee40d4207ea02364bd3b9e8e77b9159ba1eb + +# get go-zfs packages +github.com/mistifyio/go-zfs 22c9b32c84eb0d0c6f4043b6e90fc94073de92fa +github.com/pborman/uuid v1.0 + +google.golang.org/grpc v1.3.0 + +# When updating, also update RUNC_COMMIT in hack/dockerfile/binaries-commits accordingly +github.com/opencontainers/runc 0351df1c5a66838d0c392b4ac4cf9450de844e2d +github.com/opencontainers/image-spec 372ad780f63454fbbbbcc7cf80e5b90245c13e13 +github.com/opencontainers/runtime-spec v1.0.0 + +github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0 + +# libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json) +github.com/coreos/go-systemd v4 +github.com/godbus/dbus v4.0.0 +github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852 +github.com/golang/protobuf 7a211bcf3bce0e3f1d74f9894916e6f116ae83b4 + +# gelf logging driver deps +github.com/Graylog2/go-gelf v2 + +github.com/fluent/fluent-logger-golang v1.2.1 +# fluent-logger-golang deps +github.com/philhofer/fwd 98c11a7a6ec829d672b03833c3d69a7fae1ca972 +github.com/tinylib/msgp 75ee40d2601edf122ef667e2a07d600d4c44490c + +# fsnotify +github.com/fsnotify/fsnotify v1.4.2 + +# awslogs deps +github.com/aws/aws-sdk-go v1.4.22 +github.com/go-ini/ini 060d7da055ba6ec5ea7a31f116332fe5efa04ce0 +github.com/jmespath/go-jmespath 0b12d6b521d83fc7f755e7cfc1b1fbdd35a01a74 + +# logentries +github.com/bsphere/le_go 7a984a84b5492ae539b79b62fb4a10afc63c7bcf + +# gcplogs deps +golang.org/x/oauth2 96382aa079b72d8c014eb0c50f6c223d1e6a2de0 +google.golang.org/api 3cc2e591b550923a2c5f0ab5a803feda924d5823 +cloud.google.com/go 9d965e63e8cceb1b5d7977a202f0fcb8866d6525 +github.com/googleapis/gax-go da06d194a00e19ce00d9011a13931c3f6f6887c7 +google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 + +# containerd +github.com/containerd/containerd 06b9cb35161009dcb7123345749fef02f7cea8e0 +github.com/tonistiigi/fifo 1405643975692217d6720f8b54aeee1bf2cd5cf4 + +# cluster +github.com/docker/swarmkit 872861d2ae46958af7ead1d5fffb092c73afbaf0 +github.com/gogo/protobuf v0.4 +github.com/cloudflare/cfssl 7fb22c8cba7ecaf98e4082d22d65800cf45e042a +github.com/google/certificate-transparency d90e65c3a07988180c5b1ece71791c0b6506826e +golang.org/x/crypto 558b6879de74bc843225cde5686419267ff707ca +golang.org/x/time a4bde12657593d5e90d0533a3e4fd95e635124cb +github.com/hashicorp/go-memdb cb9a474f84cc5e41b273b20c6927680b2a8776ad +github.com/hashicorp/go-immutable-radix 8e8ed81f8f0bf1bdd829593fdd5c29922c1ea990 +github.com/hashicorp/golang-lru a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4 +github.com/coreos/pkg fa29b1d70f0beaddd4c7021607cc3c3be8ce94b8 +github.com/pivotal-golang/clock 3fd3c1944c59d9742e1cd333672181cd1a6f9fa0 +github.com/prometheus/client_golang 52437c81da6b127a9925d17eb3a382a2e5fd395e +github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9 +github.com/prometheus/client_model fa8ad6fec33561be4280a8f0514318c79d7f6cb6 +github.com/prometheus/common ebdfc6da46522d58825777cf1f90490a5b1ef1d8 +github.com/prometheus/procfs abf152e5f3e97f2fafac028d2cc06c1feb87ffa5 +github.com/matttproud/golang_protobuf_extensions v1.0.0 +github.com/pkg/errors 839d9e913e063e28dfd0e6c7b7512793e0a48be9 +github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0 + +# cli +github.com/spf13/cobra v1.5.1 https://github.com/dnephin/cobra.git +github.com/spf13/pflag 9ff6c6923cfffbcd502984b8e0c80539a94968b7 +github.com/inconshreveable/mousetrap 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75 +github.com/Nvveen/Gotty a8b993ba6abdb0e0c12b0125c603323a71c7790c https://github.com/ijc25/Gotty + +# metrics +github.com/docker/go-metrics d466d4f6fd960e01820085bd7e1a24426ee7ef18 + +github.com/opencontainers/selinux v1.0.0-rc1 + +# archive/tar +# mkdir -p ./vendor/archive +# git clone git://github.com/tonistiigi/go-1.git ./go +# git --git-dir ./go/.git --work-tree ./go checkout revert-prefix-ignore +# cp -a go/src/archive/tar ./vendor/archive/tar +# rm -rf ./go +# vndr diff --git a/libgo/go/cmd/go/internal/modconv/testdata/panicparse.out b/libgo/go/cmd/go/internal/modconv/testdata/panicparse.out new file mode 100644 index 00000000000..8830033c6b7 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/panicparse.out @@ -0,0 +1,8 @@ +github.com/kr/pretty 737b74a46c4bf788349f72cb256fed10aea4d0ac +github.com/kr/text 7cafcd837844e784b526369c9bce262804aebc60 +github.com/maruel/ut a9c9f15ccfa6f8b90182a53df32f4745586fbae3 +github.com/mattn/go-colorable 9056b7a9f2d1f2d96498d6d146acd1f9d5ed3d59 +github.com/mattn/go-isatty 56b76bdf51f7708750eac80fa38b952bb9f32639 +github.com/mgutz/ansi c286dcecd19ff979eeb73ea444e479b903f2cfcb +github.com/pmezard/go-difflib 792786c7400a136282c1664665ae0a8db921c6c2 +golang.org/x/sys a646d33e2ee3172a661fc09bca23bb4889a41bc8 diff --git a/libgo/go/cmd/go/internal/modconv/testdata/panicparse.vyml b/libgo/go/cmd/go/internal/modconv/testdata/panicparse.vyml new file mode 100644 index 00000000000..ff3d43f5f2d --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/panicparse.vyml @@ -0,0 +1,17 @@ +vendors: +- path: github.com/kr/pretty + rev: 737b74a46c4bf788349f72cb256fed10aea4d0ac +- path: github.com/kr/text + rev: 7cafcd837844e784b526369c9bce262804aebc60 +- path: github.com/maruel/ut + rev: a9c9f15ccfa6f8b90182a53df32f4745586fbae3 +- path: github.com/mattn/go-colorable + rev: 9056b7a9f2d1f2d96498d6d146acd1f9d5ed3d59 +- path: github.com/mattn/go-isatty + rev: 56b76bdf51f7708750eac80fa38b952bb9f32639 +- path: github.com/mgutz/ansi + rev: c286dcecd19ff979eeb73ea444e479b903f2cfcb +- path: github.com/pmezard/go-difflib + rev: 792786c7400a136282c1664665ae0a8db921c6c2 +- path: golang.org/x/sys + rev: a646d33e2ee3172a661fc09bca23bb4889a41bc8 diff --git a/libgo/go/cmd/go/internal/modconv/testdata/prometheus.out b/libgo/go/cmd/go/internal/modconv/testdata/prometheus.out new file mode 100644 index 00000000000..d11b8ecc726 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/prometheus.out @@ -0,0 +1,258 @@ +cloud.google.com/go/compute/metadata c589d0c9f0d81640c518354c7bcae77d99820aa3 +cloud.google.com/go/internal c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/Azure/azure-sdk-for-go/arm/compute bd73d950fa4440dae889bd9917bff7cef539f86e +github.com/Azure/azure-sdk-for-go/arm/network bd73d950fa4440dae889bd9917bff7cef539f86e +github.com/Azure/go-autorest/autorest 8a25372bbfec739b8719a9e3987400d15ef9e179 +github.com/Azure/go-autorest/autorest/azure 8a25372bbfec739b8719a9e3987400d15ef9e179 +github.com/Azure/go-autorest/autorest/date 8a25372bbfec739b8719a9e3987400d15ef9e179 +github.com/Azure/go-autorest/autorest/to 8a25372bbfec739b8719a9e3987400d15ef9e179 +github.com/Azure/go-autorest/autorest/validation 8a25372bbfec739b8719a9e3987400d15ef9e179 +github.com/PuerkitoBio/purell c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/PuerkitoBio/urlesc c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/asaskevich/govalidator 7b3beb6df3c42abd3509abfc3bcacc0fbfb7c877 +github.com/aws/aws-sdk-go/aws 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/awserr 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/awsutil 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/client 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/client/metadata 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/corehandlers 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/credentials 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/credentials/endpointcreds 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/credentials/stscreds 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/defaults 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/ec2metadata 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/request 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/session 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/aws/signer/v4 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/private/endpoints 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/private/protocol 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/private/protocol/ec2query 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/private/protocol/query 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/private/protocol/query/queryutil 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/private/protocol/rest 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/private/waiter 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/service/ec2 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/aws/aws-sdk-go/service/sts 707203bc55114ed114446bf57949c5c211d8b7c0 +github.com/beorn7/perks/quantile 3ac7bf7a47d159a033b107610db8a1b6575507a4 +github.com/blang/semver c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/coreos/go-oidc/http c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/coreos/go-oidc/jose c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/coreos/go-oidc/key c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/coreos/go-oidc/oauth2 c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/coreos/go-oidc/oidc c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/coreos/pkg/health c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/coreos/pkg/httputil c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/coreos/pkg/timeutil c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/davecgh/go-spew/spew c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/dgrijalva/jwt-go 9ed569b5d1ac936e6494082958d63a6aa4fff99a +github.com/docker/distribution/digest c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/docker/distribution/reference c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/emicklei/go-restful c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/emicklei/go-restful/log c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/emicklei/go-restful/swagger c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/ghodss/yaml c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/go-ini/ini 6e4869b434bd001f6983749881c7ead3545887d8 +github.com/go-openapi/jsonpointer c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/go-openapi/jsonreference c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/go-openapi/spec c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/go-openapi/swag c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/gogo/protobuf/proto c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/gogo/protobuf/sortkeys c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/golang/glog c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/golang/protobuf/proto 98fa357170587e470c5f27d3c3ea0947b71eb455 +github.com/golang/snappy d9eb7a3d35ec988b8585d4a0068e462c27d28380 +github.com/google/gofuzz c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/hashicorp/consul/api daacc4be8bee214e3fc4b32a6dd385f5ef1b4c36 +github.com/hashicorp/go-cleanhttp ad28ea4487f05916463e2423a55166280e8254b5 +github.com/hashicorp/serf/coordinate 1d4fa605f6ff3ed628d7ae5eda7c0e56803e72a5 +github.com/influxdb/influxdb/client 291aaeb9485b43b16875c238482b2f7d0a22a13b +github.com/influxdb/influxdb/tsdb 291aaeb9485b43b16875c238482b2f7d0a22a13b +github.com/jmespath/go-jmespath bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d +github.com/jonboulle/clockwork c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/juju/ratelimit c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/julienschmidt/httprouter 109e267447e95ad1bb48b758e40dd7453eb7b039 +github.com/mailru/easyjson/buffer c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/mailru/easyjson/jlexer c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/mailru/easyjson/jwriter c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/matttproud/golang_protobuf_extensions/pbutil fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a +github.com/miekg/dns 58f52c57ce9df13460ac68200cef30a008b9c468 +github.com/pborman/uuid c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/pmezard/go-difflib/difflib d77da356e56a7428ad25149ca77381849a6a5232 +github.com/prometheus/client_golang/prometheus c5b7fccd204277076155f10851dad72b76a49317 +github.com/prometheus/client_model/go fa8ad6fec33561be4280a8f0514318c79d7f6cb6 +github.com/prometheus/common/expfmt 85637ea67b04b5c3bb25e671dacded2977f8f9f6 +github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg 85637ea67b04b5c3bb25e671dacded2977f8f9f6 +github.com/prometheus/common/log 85637ea67b04b5c3bb25e671dacded2977f8f9f6 +github.com/prometheus/common/model 85637ea67b04b5c3bb25e671dacded2977f8f9f6 +github.com/prometheus/common/route 85637ea67b04b5c3bb25e671dacded2977f8f9f6 +github.com/prometheus/common/version 85637ea67b04b5c3bb25e671dacded2977f8f9f6 +github.com/prometheus/procfs abf152e5f3e97f2fafac028d2cc06c1feb87ffa5 +github.com/samuel/go-zookeeper/zk 177002e16a0061912f02377e2dd8951a8b3551bc +github.com/spf13/pflag c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/stretchr/testify/assert d77da356e56a7428ad25149ca77381849a6a5232 +github.com/stretchr/testify/require d77da356e56a7428ad25149ca77381849a6a5232 +github.com/syndtr/goleveldb/leveldb 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/syndtr/goleveldb/leveldb/cache 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/syndtr/goleveldb/leveldb/comparer 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/syndtr/goleveldb/leveldb/errors 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/syndtr/goleveldb/leveldb/filter 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/syndtr/goleveldb/leveldb/iterator 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/syndtr/goleveldb/leveldb/journal 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/syndtr/goleveldb/leveldb/memdb 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/syndtr/goleveldb/leveldb/opt 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/syndtr/goleveldb/leveldb/storage 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/syndtr/goleveldb/leveldb/table 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/syndtr/goleveldb/leveldb/util 6b4daa5362b502898ddf367c5c11deb9e7a5c727 +github.com/ugorji/go/codec c589d0c9f0d81640c518354c7bcae77d99820aa3 +github.com/vaughan0/go-ini a98ad7ee00ec53921f08832bc06ecf7fd600e6a1 +golang.org/x/net/context b336a971b799939dd16ae9b1df8334cb8b977c4d +golang.org/x/net/context/ctxhttp b336a971b799939dd16ae9b1df8334cb8b977c4d +golang.org/x/net/http2 c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/net/http2/hpack c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/net/idna c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/net/internal/timeseries 6250b412798208e6c90b03b7c4f226de5aa299e2 +golang.org/x/net/lex/httplex c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/net/netutil bc3663df0ac92f928d419e31e0d2af22e683a5a2 +golang.org/x/oauth2 65a8d08c6292395d47053be10b3c5e91960def76 +golang.org/x/oauth2/google 65a8d08c6292395d47053be10b3c5e91960def76 +golang.org/x/oauth2/internal 65a8d08c6292395d47053be10b3c5e91960def76 +golang.org/x/oauth2/jws 65a8d08c6292395d47053be10b3c5e91960def76 +golang.org/x/oauth2/jwt 65a8d08c6292395d47053be10b3c5e91960def76 +golang.org/x/sys/unix c200b10b5d5e122be351b67af224adc6128af5bf +golang.org/x/sys/windows c200b10b5d5e122be351b67af224adc6128af5bf +golang.org/x/sys/windows/registry c200b10b5d5e122be351b67af224adc6128af5bf +golang.org/x/sys/windows/svc/eventlog c200b10b5d5e122be351b67af224adc6128af5bf +golang.org/x/text/cases c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/text/internal/tag c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/text/language c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/text/runes c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/text/secure/bidirule c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/text/secure/precis c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/text/transform c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/text/unicode/bidi c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/text/unicode/norm c589d0c9f0d81640c518354c7bcae77d99820aa3 +golang.org/x/text/width c589d0c9f0d81640c518354c7bcae77d99820aa3 +google.golang.org/api/compute/v1 63ade871fd3aec1225809d496e81ec91ab76ea29 +google.golang.org/api/gensupport 63ade871fd3aec1225809d496e81ec91ab76ea29 +google.golang.org/api/googleapi 63ade871fd3aec1225809d496e81ec91ab76ea29 +google.golang.org/api/googleapi/internal/uritemplates 63ade871fd3aec1225809d496e81ec91ab76ea29 +google.golang.org/appengine 267c27e7492265b84fc6719503b14a1e17975d79 +google.golang.org/appengine/internal 267c27e7492265b84fc6719503b14a1e17975d79 +google.golang.org/appengine/internal/app_identity 267c27e7492265b84fc6719503b14a1e17975d79 +google.golang.org/appengine/internal/base 267c27e7492265b84fc6719503b14a1e17975d79 +google.golang.org/appengine/internal/datastore 267c27e7492265b84fc6719503b14a1e17975d79 +google.golang.org/appengine/internal/log 267c27e7492265b84fc6719503b14a1e17975d79 +google.golang.org/appengine/internal/modules 267c27e7492265b84fc6719503b14a1e17975d79 +google.golang.org/appengine/internal/remote_api 4f7eeb5305a4ba1966344836ba4af9996b7b4e05 +google.golang.org/appengine/internal/urlfetch 267c27e7492265b84fc6719503b14a1e17975d79 +google.golang.org/appengine/urlfetch 267c27e7492265b84fc6719503b14a1e17975d79 +google.golang.org/cloud/compute/metadata 0a83eba2cadb60eb22123673c8fb6fca02b03c94 +google.golang.org/cloud/internal 0a83eba2cadb60eb22123673c8fb6fca02b03c94 +gopkg.in/fsnotify.v1 30411dbcefb7a1da7e84f75530ad3abe4011b4f8 +gopkg.in/inf.v0 c589d0c9f0d81640c518354c7bcae77d99820aa3 +gopkg.in/yaml.v2 7ad95dd0798a40da1ccdff6dff35fd177b5edf40 +k8s.io/client-go/1.5/discovery c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes/typed/apps/v1alpha1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes/typed/authentication/v1beta1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes/typed/authorization/v1beta1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes/typed/autoscaling/v1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes/typed/batch/v1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes/typed/certificates/v1alpha1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes/typed/core/v1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes/typed/extensions/v1beta1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes/typed/policy/v1alpha1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes/typed/rbac/v1alpha1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/kubernetes/typed/storage/v1beta1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/api c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/api/errors c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/api/install c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/api/meta c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/api/meta/metatypes c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/api/resource c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/api/unversioned c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/api/v1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/api/validation/path c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apimachinery c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apimachinery/announced c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apimachinery/registered c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/apps c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/apps/install c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/apps/v1alpha1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/authentication c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/authentication/install c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/authentication/v1beta1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/authorization c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/authorization/install c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/authorization/v1beta1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/autoscaling c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/autoscaling/install c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/autoscaling/v1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/batch c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/batch/install c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/batch/v1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/batch/v2alpha1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/certificates c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/certificates/install c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/certificates/v1alpha1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/extensions c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/extensions/install c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/extensions/v1beta1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/policy c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/policy/install c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/policy/v1alpha1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/rbac c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/rbac/install c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/rbac/v1alpha1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/storage c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/storage/install c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/apis/storage/v1beta1 c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/auth/user c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/conversion c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/conversion/queryparams c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/fields c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/genericapiserver/openapi/common c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/labels c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/runtime c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/runtime/serializer c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/runtime/serializer/json c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/runtime/serializer/protobuf c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/runtime/serializer/recognizer c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/runtime/serializer/streaming c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/runtime/serializer/versioning c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/selection c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/third_party/forked/golang/reflect c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/types c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/cert c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/clock c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/errors c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/flowcontrol c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/framer c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/integer c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/intstr c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/json c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/labels c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/net c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/parsers c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/rand c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/runtime c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/sets c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/uuid c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/validation c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/validation/field c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/wait c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/util/yaml c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/version c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/watch c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/pkg/watch/versioned c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/plugin/pkg/client/auth c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/plugin/pkg/client/auth/gcp c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/plugin/pkg/client/auth/oidc c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/rest c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/tools/cache c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/tools/clientcmd/api c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/tools/metrics c589d0c9f0d81640c518354c7bcae77d99820aa3 +k8s.io/client-go/1.5/transport c589d0c9f0d81640c518354c7bcae77d99820aa3 diff --git a/libgo/go/cmd/go/internal/modconv/testdata/prometheus.vjson b/libgo/go/cmd/go/internal/modconv/testdata/prometheus.vjson new file mode 100644 index 00000000000..648bec42608 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/prometheus.vjson @@ -0,0 +1,1605 @@ +{ + "comment": "", + "ignore": "test appengine", + "package": [ + { + "checksumSHA1": "Cslv4/ITyQmgjSUhNXFu8q5bqOU=", + "origin": "k8s.io/client-go/1.5/vendor/cloud.google.com/go/compute/metadata", + "path": "cloud.google.com/go/compute/metadata", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "hiJXjkFEGy+sDFf6O58Ocdy9Rnk=", + "origin": "k8s.io/client-go/1.5/vendor/cloud.google.com/go/internal", + "path": "cloud.google.com/go/internal", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "oIt4tXgFYnZJBsCac1BQLnTWALM=", + "path": "github.com/Azure/azure-sdk-for-go/arm/compute", + "revision": "bd73d950fa4440dae889bd9917bff7cef539f86e", + "revisionTime": "2016-10-28T18:31:11Z" + }, + { + "checksumSHA1": "QKi6LiSyD5GnRK8ExpMgZl4XiMI=", + "path": "github.com/Azure/azure-sdk-for-go/arm/network", + "revision": "bd73d950fa4440dae889bd9917bff7cef539f86e", + "revisionTime": "2016-10-28T18:31:11Z" + }, + { + "checksumSHA1": "eVSHe6GIHj9/ziFrQLZ1SC7Nn6k=", + "path": "github.com/Azure/go-autorest/autorest", + "revision": "8a25372bbfec739b8719a9e3987400d15ef9e179", + "revisionTime": "2016-10-25T18:07:34Z" + }, + { + "checksumSHA1": "0sYi0JprevG/PZjtMbOh8h0pt0g=", + "path": "github.com/Azure/go-autorest/autorest/azure", + "revision": "8a25372bbfec739b8719a9e3987400d15ef9e179", + "revisionTime": "2016-10-25T18:07:34Z" + }, + { + "checksumSHA1": "q9Qz8PAxK5FTOZwgYKe5Lj38u4c=", + "path": "github.com/Azure/go-autorest/autorest/date", + "revision": "8a25372bbfec739b8719a9e3987400d15ef9e179", + "revisionTime": "2016-10-25T18:07:34Z" + }, + { + "checksumSHA1": "Ev8qCsbFjDlMlX0N2tYAhYQFpUc=", + "path": "github.com/Azure/go-autorest/autorest/to", + "revision": "8a25372bbfec739b8719a9e3987400d15ef9e179", + "revisionTime": "2016-10-25T18:07:34Z" + }, + { + "checksumSHA1": "oBixceM+55gdk47iff8DSEIh3po=", + "path": "github.com/Azure/go-autorest/autorest/validation", + "revision": "8a25372bbfec739b8719a9e3987400d15ef9e179", + "revisionTime": "2016-10-25T18:07:34Z" + }, + { + "checksumSHA1": "IatnluZB5jTVUncMN134e4VOV34=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/PuerkitoBio/purell", + "path": "github.com/PuerkitoBio/purell", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "E/Tz8z0B/gaR551g+XqPKAhcteM=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/PuerkitoBio/urlesc", + "path": "github.com/PuerkitoBio/urlesc", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "BdLdZP/C2uOO3lqk9X3NCKFpXa4=", + "path": "github.com/asaskevich/govalidator", + "revision": "7b3beb6df3c42abd3509abfc3bcacc0fbfb7c877", + "revisionTime": "2016-10-01T16:31:30Z" + }, + { + "checksumSHA1": "WNfR3yhLjRC5/uccgju/bwrdsxQ=", + "path": "github.com/aws/aws-sdk-go/aws", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "Y9W+4GimK4Fuxq+vyIskVYFRnX4=", + "path": "github.com/aws/aws-sdk-go/aws/awserr", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "+q4vdl3l1Wom8K1wfIpJ4jlFsbY=", + "path": "github.com/aws/aws-sdk-go/aws/awsutil", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "/232RBWA3KnT7U+wciPS2+wmvR0=", + "path": "github.com/aws/aws-sdk-go/aws/client", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "ieAJ+Cvp/PKv1LpUEnUXpc3OI6E=", + "path": "github.com/aws/aws-sdk-go/aws/client/metadata", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "c1N3Loy3AS9zD+m5CzpPNAED39U=", + "path": "github.com/aws/aws-sdk-go/aws/corehandlers", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "zu5C95rmCZff6NYZb62lEaT5ibE=", + "path": "github.com/aws/aws-sdk-go/aws/credentials", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "KQiUK/zr3mqnAXD7x/X55/iNme0=", + "path": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "NUJUTWlc1sV8b7WjfiYc4JZbXl0=", + "path": "github.com/aws/aws-sdk-go/aws/credentials/endpointcreds", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "4Ipx+5xN0gso+cENC2MHMWmQlR4=", + "path": "github.com/aws/aws-sdk-go/aws/credentials/stscreds", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "DwhFsNluCFEwqzyp3hbJR3q2Wqs=", + "path": "github.com/aws/aws-sdk-go/aws/defaults", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "8E0fEBUJY/1lJOyVxzTxMGQGInk=", + "path": "github.com/aws/aws-sdk-go/aws/ec2metadata", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "5Ac22YMTBmrX/CXaEIXzWljr8UY=", + "path": "github.com/aws/aws-sdk-go/aws/request", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "eOo6evLMAxQfo7Qkc5/h5euN1Sw=", + "path": "github.com/aws/aws-sdk-go/aws/session", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "diXvBs1LRC0RJ9WK6sllWKdzC04=", + "path": "github.com/aws/aws-sdk-go/aws/signer/v4", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "Esab5F8KswqkTdB4TtjSvZgs56k=", + "path": "github.com/aws/aws-sdk-go/private/endpoints", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "wk7EyvDaHwb5qqoOP/4d3cV0708=", + "path": "github.com/aws/aws-sdk-go/private/protocol", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "1QmQ3FqV37w0Zi44qv8pA1GeR0A=", + "path": "github.com/aws/aws-sdk-go/private/protocol/ec2query", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "ZqY5RWavBLWTo6j9xqdyBEaNFRk=", + "path": "github.com/aws/aws-sdk-go/private/protocol/query", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "5xzix1R8prUyWxgLnzUQoxTsfik=", + "path": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "TW/7U+/8ormL7acf6z2rv2hDD+s=", + "path": "github.com/aws/aws-sdk-go/private/protocol/rest", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "eUEkjyMPAuekKBE4ou+nM9tXEas=", + "path": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "Eo9yODN5U99BK0pMzoqnBm7PCrY=", + "path": "github.com/aws/aws-sdk-go/private/waiter", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "6h4tJ9wVtbYb9wG4srtUxyPoAYM=", + "path": "github.com/aws/aws-sdk-go/service/ec2", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "ouwhxcAsIYQ6oJbMRdLW/Ys/iyg=", + "path": "github.com/aws/aws-sdk-go/service/sts", + "revision": "707203bc55114ed114446bf57949c5c211d8b7c0", + "revisionTime": "2016-11-02T21:59:28Z" + }, + { + "checksumSHA1": "4QnLdmB1kG3N+KlDd1N+G9TWAGQ=", + "path": "github.com/beorn7/perks/quantile", + "revision": "3ac7bf7a47d159a033b107610db8a1b6575507a4", + "revisionTime": "2016-02-29T21:34:45Z" + }, + { + "checksumSHA1": "n+s4YwtzpMWW5Rt0dEaQa7NHDGQ=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/blang/semver", + "path": "github.com/blang/semver", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "Z2AOGSmDKKvI6nuxa+UPjQWpIeM=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/coreos/go-oidc/http", + "path": "github.com/coreos/go-oidc/http", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "8yvt1xKCgNwuuavJdxRnvaIjrIc=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/coreos/go-oidc/jose", + "path": "github.com/coreos/go-oidc/jose", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "zhXKrWBSSJLqZxVE/Xsw0M9ynFQ=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/coreos/go-oidc/key", + "path": "github.com/coreos/go-oidc/key", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "bkW0mnXvmHQwHprW/6wrbpP7lAk=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/coreos/go-oidc/oauth2", + "path": "github.com/coreos/go-oidc/oauth2", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "E1x2k5FdhJ+dzFrh3kCmC6aJfVw=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/coreos/go-oidc/oidc", + "path": "github.com/coreos/go-oidc/oidc", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "O0UMBRCOD9ItMayDqLQ2MJEjkVE=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/coreos/pkg/health", + "path": "github.com/coreos/pkg/health", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "74vyZz/d49FZXMbFaHOfCGvSLj0=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/coreos/pkg/httputil", + "path": "github.com/coreos/pkg/httputil", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "etBdQ0LN6ojGunfvUt6B5C3FNrQ=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/coreos/pkg/timeutil", + "path": "github.com/coreos/pkg/timeutil", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "SdSd7pyjONWWTHc5XE3AhglLo34=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/davecgh/go-spew/spew", + "path": "github.com/davecgh/go-spew/spew", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "2Fy1Y6Z3lRRX1891WF/+HT4XS2I=", + "path": "github.com/dgrijalva/jwt-go", + "revision": "9ed569b5d1ac936e6494082958d63a6aa4fff99a", + "revisionTime": "2016-11-01T19:39:35Z" + }, + { + "checksumSHA1": "f1wARLDzsF/JoyN01yoxXEwFIp8=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/docker/distribution/digest", + "path": "github.com/docker/distribution/digest", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "PzXRTLmmqWXxmDqdIXLcRYBma18=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/docker/distribution/reference", + "path": "github.com/docker/distribution/reference", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "1vQR+ZyudsjKio6RNKmWhwzGTb0=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/emicklei/go-restful", + "path": "github.com/emicklei/go-restful", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "3xWz4fZ9xW+CfADpYoPFcZCYJ4E=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/emicklei/go-restful/log", + "path": "github.com/emicklei/go-restful/log", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "J7CtF9gIs2yH9A7lPQDDrhYxiRk=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/emicklei/go-restful/swagger", + "path": "github.com/emicklei/go-restful/swagger", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "ww7LVo7jNJ1o6sfRcromEHKyY+o=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/ghodss/yaml", + "path": "github.com/ghodss/yaml", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "cVyhKIRI2gQrgpn5qrBeAqErmWM=", + "path": "github.com/go-ini/ini", + "revision": "6e4869b434bd001f6983749881c7ead3545887d8", + "revisionTime": "2016-08-27T06:11:18Z" + }, + { + "checksumSHA1": "NaZnW0tKj/b0k5WzcMD0twrLbrE=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/go-openapi/jsonpointer", + "path": "github.com/go-openapi/jsonpointer", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "3LJXjMDxPY+veIqzQtiAvK3hXnY=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/go-openapi/jsonreference", + "path": "github.com/go-openapi/jsonreference", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "faeB3fny260hQ/gEfEXa1ZQTGtk=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/go-openapi/spec", + "path": "github.com/go-openapi/spec", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "wGpZwJ5HZtReou8A3WEV1Gdxs6k=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/go-openapi/swag", + "path": "github.com/go-openapi/swag", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "BIyZQL97iG7mzZ2UMR3XpiXbZdc=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/gogo/protobuf/proto", + "path": "github.com/gogo/protobuf/proto", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "e6cMbpJj41MpihS5eP4SIliRBK4=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/gogo/protobuf/sortkeys", + "path": "github.com/gogo/protobuf/sortkeys", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "URsJa4y/sUUw/STmbeYx9EKqaYE=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/golang/glog", + "path": "github.com/golang/glog", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "yDh5kmmr0zEF1r+rvYqbZcR7iLs=", + "path": "github.com/golang/protobuf/proto", + "revision": "98fa357170587e470c5f27d3c3ea0947b71eb455", + "revisionTime": "2016-10-12T20:53:35Z" + }, + { + "checksumSHA1": "2a/SsTUBMKtcM6VtpbdPGO+c6c8=", + "path": "github.com/golang/snappy", + "revision": "d9eb7a3d35ec988b8585d4a0068e462c27d28380", + "revisionTime": "2016-05-29T05:00:41Z" + }, + { + "checksumSHA1": "/yFfUp3tGt6cK22UVzbq8SjPDCU=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/google/gofuzz", + "path": "github.com/google/gofuzz", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "LclVLJYrBi03PBjsVPpgoMbUDQ8=", + "path": "github.com/hashicorp/consul/api", + "revision": "daacc4be8bee214e3fc4b32a6dd385f5ef1b4c36", + "revisionTime": "2016-10-28T04:06:46Z" + }, + { + "checksumSHA1": "Uzyon2091lmwacNsl1hCytjhHtg=", + "path": "github.com/hashicorp/go-cleanhttp", + "revision": "ad28ea4487f05916463e2423a55166280e8254b5", + "revisionTime": "2016-04-07T17:41:26Z" + }, + { + "checksumSHA1": "E3Xcanc9ouQwL+CZGOUyA/+giLg=", + "path": "github.com/hashicorp/serf/coordinate", + "revision": "1d4fa605f6ff3ed628d7ae5eda7c0e56803e72a5", + "revisionTime": "2016-10-07T00:41:22Z" + }, + { + "path": "github.com/influxdb/influxdb/client", + "revision": "291aaeb9485b43b16875c238482b2f7d0a22a13b", + "revisionTime": "2015-09-16T14:41:53+02:00" + }, + { + "path": "github.com/influxdb/influxdb/tsdb", + "revision": "291aaeb9485b43b16875c238482b2f7d0a22a13b", + "revisionTime": "2015-09-16T14:41:53+02:00" + }, + { + "checksumSHA1": "0ZrwvB6KoGPj2PoDNSEJwxQ6Mog=", + "path": "github.com/jmespath/go-jmespath", + "revision": "bd40a432e4c76585ef6b72d3fd96fb9b6dc7b68d", + "revisionTime": "2016-08-03T19:07:31Z" + }, + { + "checksumSHA1": "9ZVOEbIXnTuYpVqce4en8rwlkPE=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/jonboulle/clockwork", + "path": "github.com/jonboulle/clockwork", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "gA95N2LM2hEJLoqrTPaFsSWDJ2Y=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/juju/ratelimit", + "path": "github.com/juju/ratelimit", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "Farach1xcmsQYrhiUfkwF2rbIaE=", + "path": "github.com/julienschmidt/httprouter", + "revision": "109e267447e95ad1bb48b758e40dd7453eb7b039", + "revisionTime": "2015-09-05T19:25:33+02:00" + }, + { + "checksumSHA1": "urY45++NYCue4nh4k8OjUFnIGfU=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/mailru/easyjson/buffer", + "path": "github.com/mailru/easyjson/buffer", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "yTDKAM4KBgOvXRsZC50zg0OChvM=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/mailru/easyjson/jlexer", + "path": "github.com/mailru/easyjson/jlexer", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "4+d+6rhM1pei6lBguhqSEW7LaXs=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/mailru/easyjson/jwriter", + "path": "github.com/mailru/easyjson/jwriter", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "Q2vw4HZBbnU8BLFt8VrzStwqSJg=", + "path": "github.com/matttproud/golang_protobuf_extensions/pbutil", + "revision": "fc2b8d3a73c4867e51861bbdd5ae3c1f0869dd6a", + "revisionTime": "2015-04-06T19:39:34+02:00" + }, + { + "checksumSHA1": "Wahi4g/9XiHhSLAJ+8jskg71PCU=", + "path": "github.com/miekg/dns", + "revision": "58f52c57ce9df13460ac68200cef30a008b9c468", + "revisionTime": "2016-10-18T06:08:08Z" + }, + { + "checksumSHA1": "3YJklSuzSE1Rt8A+2dhiWSmf/fw=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/pborman/uuid", + "path": "github.com/pborman/uuid", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "zKKp5SZ3d3ycKe4EKMNT0BqAWBw=", + "origin": "github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib", + "path": "github.com/pmezard/go-difflib/difflib", + "revision": "d77da356e56a7428ad25149ca77381849a6a5232", + "revisionTime": "2016-06-15T09:26:46Z" + }, + { + "checksumSHA1": "KkB+77Ziom7N6RzSbyUwYGrmDeU=", + "path": "github.com/prometheus/client_golang/prometheus", + "revision": "c5b7fccd204277076155f10851dad72b76a49317", + "revisionTime": "2016-08-17T15:48:24Z" + }, + { + "checksumSHA1": "DvwvOlPNAgRntBzt3b3OSRMS2N4=", + "path": "github.com/prometheus/client_model/go", + "revision": "fa8ad6fec33561be4280a8f0514318c79d7f6cb6", + "revisionTime": "2015-02-12T10:17:44Z" + }, + { + "checksumSHA1": "mHyjbJ3BWOfUV6q9f5PBt0gaY1k=", + "path": "github.com/prometheus/common/expfmt", + "revision": "85637ea67b04b5c3bb25e671dacded2977f8f9f6", + "revisionTime": "2016-10-02T21:02:34Z" + }, + { + "checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=", + "path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg", + "revision": "85637ea67b04b5c3bb25e671dacded2977f8f9f6", + "revisionTime": "2016-10-02T21:02:34Z" + }, + { + "checksumSHA1": "UU6hIfhVjnAYDADQEfE/3T7Ddm8=", + "path": "github.com/prometheus/common/log", + "revision": "85637ea67b04b5c3bb25e671dacded2977f8f9f6", + "revisionTime": "2016-10-02T21:02:34Z" + }, + { + "checksumSHA1": "nFie+rxcX5WdIv1diZ+fu3aj6lE=", + "path": "github.com/prometheus/common/model", + "revision": "85637ea67b04b5c3bb25e671dacded2977f8f9f6", + "revisionTime": "2016-10-02T21:02:34Z" + }, + { + "checksumSHA1": "QQKJYoGcY10nIHxhBEHwjwUZQzk=", + "path": "github.com/prometheus/common/route", + "revision": "85637ea67b04b5c3bb25e671dacded2977f8f9f6", + "revisionTime": "2016-10-02T21:02:34Z" + }, + { + "checksumSHA1": "91KYK0SpvkaMJJA2+BcxbVnyRO0=", + "path": "github.com/prometheus/common/version", + "revision": "85637ea67b04b5c3bb25e671dacded2977f8f9f6", + "revisionTime": "2016-10-02T21:02:34Z" + }, + { + "checksumSHA1": "W218eJZPXJG783fUr/z6IaAZyes=", + "path": "github.com/prometheus/procfs", + "revision": "abf152e5f3e97f2fafac028d2cc06c1feb87ffa5", + "revisionTime": "2016-04-11T19:08:41Z" + }, + { + "checksumSHA1": "+49Vr4Me28p3cR+gxX5SUQHbbas=", + "path": "github.com/samuel/go-zookeeper/zk", + "revision": "177002e16a0061912f02377e2dd8951a8b3551bc", + "revisionTime": "2015-08-17T10:50:50-07:00" + }, + { + "checksumSHA1": "YuPBOVkkE3uuBh4RcRUTF0n+frs=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/spf13/pflag", + "path": "github.com/spf13/pflag", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "iydUphwYqZRq3WhstEdGsbvBAKs=", + "path": "github.com/stretchr/testify/assert", + "revision": "d77da356e56a7428ad25149ca77381849a6a5232", + "revisionTime": "2016-06-15T09:26:46Z" + }, + { + "checksumSHA1": "P9FJpir2c4G5PA46qEkaWy3l60U=", + "path": "github.com/stretchr/testify/require", + "revision": "d77da356e56a7428ad25149ca77381849a6a5232", + "revisionTime": "2016-06-15T09:26:46Z" + }, + { + "checksumSHA1": "VhcnDY37sYAnL8WjfYQN9YYl+W4=", + "path": "github.com/syndtr/goleveldb/leveldb", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "EKIow7XkgNdWvR/982ffIZxKG8Y=", + "path": "github.com/syndtr/goleveldb/leveldb/cache", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "5KPgnvCPlR0ysDAqo6jApzRQ3tw=", + "path": "github.com/syndtr/goleveldb/leveldb/comparer", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "1DRAxdlWzS4U0xKN/yQ/fdNN7f0=", + "path": "github.com/syndtr/goleveldb/leveldb/errors", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "eqKeD6DS7eNCtxVYZEHHRKkyZrw=", + "path": "github.com/syndtr/goleveldb/leveldb/filter", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "8dXuAVIsbtaMiGGuHjzGR6Ny/5c=", + "path": "github.com/syndtr/goleveldb/leveldb/iterator", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "gJY7bRpELtO0PJpZXgPQ2BYFJ88=", + "path": "github.com/syndtr/goleveldb/leveldb/journal", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "j+uaQ6DwJ50dkIdfMQu1TXdlQcY=", + "path": "github.com/syndtr/goleveldb/leveldb/memdb", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "UmQeotV+m8/FduKEfLOhjdp18rs=", + "path": "github.com/syndtr/goleveldb/leveldb/opt", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "/Wvv9HeJTN9UUjdjwUlz7X4ioIo=", + "path": "github.com/syndtr/goleveldb/leveldb/storage", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "JTJA+u8zk7EXy1UUmpFPNGvtO2A=", + "path": "github.com/syndtr/goleveldb/leveldb/table", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "4zil8Gwg8VPkDn1YzlgCvtukJFU=", + "path": "github.com/syndtr/goleveldb/leveldb/util", + "revision": "6b4daa5362b502898ddf367c5c11deb9e7a5c727", + "revisionTime": "2016-10-11T05:00:08Z" + }, + { + "checksumSHA1": "f6Aew+ZA+HBAXCw6/xTST3mB0Lw=", + "origin": "k8s.io/client-go/1.5/vendor/github.com/ugorji/go/codec", + "path": "github.com/ugorji/go/codec", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "sFD8LpJPQtWLwGda3edjf5mNUbs=", + "path": "github.com/vaughan0/go-ini", + "revision": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1", + "revisionTime": "2013-09-23T16:52:12+02:00" + }, + { + "checksumSHA1": "9jjO5GjLa0XF/nfWihF02RoH4qc=", + "path": "golang.org/x/net/context", + "revision": "b336a971b799939dd16ae9b1df8334cb8b977c4d", + "revisionTime": "2016-10-27T19:58:04Z" + }, + { + "checksumSHA1": "WHc3uByvGaMcnSoI21fhzYgbOgg=", + "path": "golang.org/x/net/context/ctxhttp", + "revision": "b336a971b799939dd16ae9b1df8334cb8b977c4d", + "revisionTime": "2016-10-27T19:58:04Z" + }, + { + "checksumSHA1": "SPYGC6DQrH9jICccUsOfbvvhB4g=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/net/http2", + "path": "golang.org/x/net/http2", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "EYNaHp7XdLWRydUCE0amEkKAtgk=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/net/http2/hpack", + "path": "golang.org/x/net/http2/hpack", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "gXiSniT8fevWOVPVKopYgrdzi60=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/net/idna", + "path": "golang.org/x/net/idna", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "/k7k6eJDkxXx6K9Zpo/OwNm58XM=", + "path": "golang.org/x/net/internal/timeseries", + "revision": "6250b412798208e6c90b03b7c4f226de5aa299e2", + "revisionTime": "2016-08-24T22:20:41Z" + }, + { + "checksumSHA1": "yhndhWXMs/VSEDLks4dNyFMQStA=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/net/lex/httplex", + "path": "golang.org/x/net/lex/httplex", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "7WASrg0PEueWDDRHkFhEEN6Qrms=", + "path": "golang.org/x/net/netutil", + "revision": "bc3663df0ac92f928d419e31e0d2af22e683a5a2", + "revisionTime": "2016-06-21T20:48:10Z" + }, + { + "checksumSHA1": "mktBVED98G2vv+OKcSgtnFVZC1Y=", + "path": "golang.org/x/oauth2", + "revision": "65a8d08c6292395d47053be10b3c5e91960def76", + "revisionTime": "2016-06-07T03:33:14Z" + }, + { + "checksumSHA1": "2rk6lthfQa5Rfydj8j7+dilKGbo=", + "path": "golang.org/x/oauth2/google", + "revision": "65a8d08c6292395d47053be10b3c5e91960def76", + "revisionTime": "2016-06-07T03:33:14Z" + }, + { + "checksumSHA1": "W/GiDqzsagBnR7/yEvxatMhUDBs=", + "path": "golang.org/x/oauth2/internal", + "revision": "65a8d08c6292395d47053be10b3c5e91960def76", + "revisionTime": "2016-06-07T03:33:14Z" + }, + { + "checksumSHA1": "CPTYHWrVL4jA0B1IuC0hvgcE2AQ=", + "path": "golang.org/x/oauth2/jws", + "revision": "65a8d08c6292395d47053be10b3c5e91960def76", + "revisionTime": "2016-06-07T03:33:14Z" + }, + { + "checksumSHA1": "xifBSq0Pn6pIoPA/o3tyzq8X4Ds=", + "path": "golang.org/x/oauth2/jwt", + "revision": "65a8d08c6292395d47053be10b3c5e91960def76", + "revisionTime": "2016-06-07T03:33:14Z" + }, + { + "checksumSHA1": "aVgPDgwY3/t4J/JOw9H3FVMHqh0=", + "path": "golang.org/x/sys/unix", + "revision": "c200b10b5d5e122be351b67af224adc6128af5bf", + "revisionTime": "2016-10-22T18:22:21Z" + }, + { + "checksumSHA1": "fpW2dhGFC6SrVzipJx7fjg2DIH8=", + "path": "golang.org/x/sys/windows", + "revision": "c200b10b5d5e122be351b67af224adc6128af5bf", + "revisionTime": "2016-10-22T18:22:21Z" + }, + { + "checksumSHA1": "PjYlbMS0ttyZYlaevvjA/gV3g1c=", + "path": "golang.org/x/sys/windows/registry", + "revision": "c200b10b5d5e122be351b67af224adc6128af5bf", + "revisionTime": "2016-10-22T18:22:21Z" + }, + { + "checksumSHA1": "uVlUSSKplihZG7N+QJ6fzDZ4Kh8=", + "path": "golang.org/x/sys/windows/svc/eventlog", + "revision": "c200b10b5d5e122be351b67af224adc6128af5bf", + "revisionTime": "2016-10-22T18:22:21Z" + }, + { + "checksumSHA1": "QQpKbWuqvhmxVr/hfEYdWzzcXRM=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/text/cases", + "path": "golang.org/x/text/cases", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "iAsGo/kxvnwILbJVUCd0ZcqZO/Q=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/text/internal/tag", + "path": "golang.org/x/text/internal/tag", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "mQ6PCGHY7K0oPjKbYD8wsTjm/P8=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/text/language", + "path": "golang.org/x/text/language", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "WpeH2TweiuiZAQVTJNO5vyZAQQA=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/text/runes", + "path": "golang.org/x/text/runes", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "1VjEPyjdi0xOiIN/Alkqiad/B/c=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/text/secure/bidirule", + "path": "golang.org/x/text/secure/bidirule", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "FcK7VslktIAWj5jnWVnU2SesBq0=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/text/secure/precis", + "path": "golang.org/x/text/secure/precis", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "nwlu7UTwYbCj9l5f3a7t2ROwNzM=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/text/transform", + "path": "golang.org/x/text/transform", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "nWJ9R1+Xw41f/mM3b7BYtv77CfI=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/text/unicode/bidi", + "path": "golang.org/x/text/unicode/bidi", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "BAZ96wCGUj6HdY9sG60Yw09KWA4=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/text/unicode/norm", + "path": "golang.org/x/text/unicode/norm", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "AZMILKWqLP99UilLgbGZ+uzIVrM=", + "origin": "k8s.io/client-go/1.5/vendor/golang.org/x/text/width", + "path": "golang.org/x/text/width", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "AjdmRXf0fiy6Bec9mNlsGsmZi1k=", + "path": "google.golang.org/api/compute/v1", + "revision": "63ade871fd3aec1225809d496e81ec91ab76ea29", + "revisionTime": "2016-05-31T06:42:46Z" + }, + { + "checksumSHA1": "OtsMVXY89Hc/bBXdDp84atFQawM=", + "path": "google.golang.org/api/gensupport", + "revision": "63ade871fd3aec1225809d496e81ec91ab76ea29", + "revisionTime": "2016-05-31T06:42:46Z" + }, + { + "checksumSHA1": "yQREK/OWrz9PLljbr127+xFk6J0=", + "path": "google.golang.org/api/googleapi", + "revision": "63ade871fd3aec1225809d496e81ec91ab76ea29", + "revisionTime": "2016-05-31T06:42:46Z" + }, + { + "checksumSHA1": "ii4ET3JHk3vkMUEcg+9t/1RZSUU=", + "path": "google.golang.org/api/googleapi/internal/uritemplates", + "revision": "63ade871fd3aec1225809d496e81ec91ab76ea29", + "revisionTime": "2016-05-31T06:42:46Z" + }, + { + "checksumSHA1": "N3KZEuQ9O1QwJXcCJbe7Czwroo4=", + "path": "google.golang.org/appengine", + "revision": "267c27e7492265b84fc6719503b14a1e17975d79", + "revisionTime": "2016-06-21T05:59:22Z" + }, + { + "checksumSHA1": "G9Xp1ScdsfcKsw+PcWunivRRP3o=", + "path": "google.golang.org/appengine/internal", + "revision": "267c27e7492265b84fc6719503b14a1e17975d79", + "revisionTime": "2016-06-21T05:59:22Z" + }, + { + "checksumSHA1": "x6Thdfyasqd68dWZWqzWWeIfAfI=", + "path": "google.golang.org/appengine/internal/app_identity", + "revision": "267c27e7492265b84fc6719503b14a1e17975d79", + "revisionTime": "2016-06-21T05:59:22Z" + }, + { + "checksumSHA1": "TsNO8P0xUlLNyh3Ic/tzSp/fDWM=", + "path": "google.golang.org/appengine/internal/base", + "revision": "267c27e7492265b84fc6719503b14a1e17975d79", + "revisionTime": "2016-06-21T05:59:22Z" + }, + { + "checksumSHA1": "5QsV5oLGSfKZqTCVXP6NRz5T4Tw=", + "path": "google.golang.org/appengine/internal/datastore", + "revision": "267c27e7492265b84fc6719503b14a1e17975d79", + "revisionTime": "2016-06-21T05:59:22Z" + }, + { + "checksumSHA1": "Gep2T9zmVYV8qZfK2gu3zrmG6QE=", + "path": "google.golang.org/appengine/internal/log", + "revision": "267c27e7492265b84fc6719503b14a1e17975d79", + "revisionTime": "2016-06-21T05:59:22Z" + }, + { + "checksumSHA1": "eLZVX1EHLclFtQnjDIszsdyWRHo=", + "path": "google.golang.org/appengine/internal/modules", + "revision": "267c27e7492265b84fc6719503b14a1e17975d79", + "revisionTime": "2016-06-21T05:59:22Z" + }, + { + "checksumSHA1": "a1XY7rz3BieOVqVI2Et6rKiwQCk=", + "path": "google.golang.org/appengine/internal/remote_api", + "revision": "4f7eeb5305a4ba1966344836ba4af9996b7b4e05", + "revisionTime": "2016-08-19T23:33:10Z" + }, + { + "checksumSHA1": "QtAbHtHmDzcf6vOV9eqlCpKgjiw=", + "path": "google.golang.org/appengine/internal/urlfetch", + "revision": "267c27e7492265b84fc6719503b14a1e17975d79", + "revisionTime": "2016-06-21T05:59:22Z" + }, + { + "checksumSHA1": "akOV9pYnCbcPA8wJUutSQVibdyg=", + "path": "google.golang.org/appengine/urlfetch", + "revision": "267c27e7492265b84fc6719503b14a1e17975d79", + "revisionTime": "2016-06-21T05:59:22Z" + }, + { + "checksumSHA1": "Wp8g9MHRmK8SwcyGVCoGtPx+5Lo=", + "path": "google.golang.org/cloud/compute/metadata", + "revision": "0a83eba2cadb60eb22123673c8fb6fca02b03c94", + "revisionTime": "2016-06-21T15:59:29Z" + }, + { + "checksumSHA1": "U7dGDNwEHORvJFMoNSXErKE7ITg=", + "path": "google.golang.org/cloud/internal", + "revision": "0a83eba2cadb60eb22123673c8fb6fca02b03c94", + "revisionTime": "2016-06-21T15:59:29Z" + }, + { + "checksumSHA1": "JfVmsMwyeeepbdw4q4wpN07BuFg=", + "path": "gopkg.in/fsnotify.v1", + "revision": "30411dbcefb7a1da7e84f75530ad3abe4011b4f8", + "revisionTime": "2016-04-12T13:37:56Z" + }, + { + "checksumSHA1": "pfQwQtWlFezJq0Viroa/L+v+yDM=", + "origin": "k8s.io/client-go/1.5/vendor/gopkg.in/inf.v0", + "path": "gopkg.in/inf.v0", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "KgT+peLCcuh0/m2mpoOZXuxXmwc=", + "path": "gopkg.in/yaml.v2", + "revision": "7ad95dd0798a40da1ccdff6dff35fd177b5edf40", + "revisionTime": "2015-06-24T11:29:02+01:00" + }, + { + "checksumSHA1": "st0Nbu4zwLcP3mz03lDOJVZtn8Y=", + "path": "k8s.io/client-go/1.5/discovery", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "S+OzpkipMb46LGZoWuveqSLAcoM=", + "path": "k8s.io/client-go/1.5/kubernetes", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "yCBn8ig1TUMrk+ljtK0nDr7E5Vo=", + "path": "k8s.io/client-go/1.5/kubernetes/typed/apps/v1alpha1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "ZRnUz5NrpvJsXAjtnRdEv5UYhSI=", + "path": "k8s.io/client-go/1.5/kubernetes/typed/authentication/v1beta1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "TY55Np20olmPMzXgfVlIUIyqv04=", + "path": "k8s.io/client-go/1.5/kubernetes/typed/authorization/v1beta1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "FRByJsFff/6lPH20FtJPaK1NPWI=", + "path": "k8s.io/client-go/1.5/kubernetes/typed/autoscaling/v1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "3Cy2as7HnQ2FDcvpNbatpFWx0P4=", + "path": "k8s.io/client-go/1.5/kubernetes/typed/batch/v1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "RUKywApIbSLLsfkYxXzifh7HIvs=", + "path": "k8s.io/client-go/1.5/kubernetes/typed/certificates/v1alpha1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "4+Lsxu+sYgzsS2JOHP7CdrZLSKc=", + "path": "k8s.io/client-go/1.5/kubernetes/typed/core/v1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "H8jzevN03YUfmf2krJt0qj2P9sU=", + "path": "k8s.io/client-go/1.5/kubernetes/typed/extensions/v1beta1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "hrpA6xxtwj3oMcQbFxI2cDhO2ZA=", + "path": "k8s.io/client-go/1.5/kubernetes/typed/policy/v1alpha1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "B2+F12NeMwrOHvHK2ALyEcr3UGA=", + "path": "k8s.io/client-go/1.5/kubernetes/typed/rbac/v1alpha1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "h2eSNUym87RWPlez7UKujShwrUQ=", + "path": "k8s.io/client-go/1.5/kubernetes/typed/storage/v1beta1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "+oIykJ3A0wYjAWbbrGo0jNnMLXw=", + "path": "k8s.io/client-go/1.5/pkg/api", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "UsUsIdhuy5Ej2vI0hbmSsrimoaQ=", + "path": "k8s.io/client-go/1.5/pkg/api/errors", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "Eo6LLHFqG6YznIAKr2mVjuqUj6k=", + "path": "k8s.io/client-go/1.5/pkg/api/install", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "dYznkLcCEai21z1dX8kZY7uDsck=", + "path": "k8s.io/client-go/1.5/pkg/api/meta", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "b06esG4xMj/YNFD85Lqq00cx+Yo=", + "path": "k8s.io/client-go/1.5/pkg/api/meta/metatypes", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "L9svak1yut0Mx8r9VLDOwpqZzBk=", + "path": "k8s.io/client-go/1.5/pkg/api/resource", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "m7jGshKDLH9kdokfa6MwAqzxRQk=", + "path": "k8s.io/client-go/1.5/pkg/api/unversioned", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "iI6s5WAexr1PEfqrbvuscB+oVik=", + "path": "k8s.io/client-go/1.5/pkg/api/v1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "ikac34qI/IkTWHnfi8pPl9irPyo=", + "path": "k8s.io/client-go/1.5/pkg/api/validation/path", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "MJyygSPp8N6z+7SPtcROz4PEwas=", + "path": "k8s.io/client-go/1.5/pkg/apimachinery", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "EGb4IcSTQ1VXCmX0xcyG5GpWId8=", + "path": "k8s.io/client-go/1.5/pkg/apimachinery/announced", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "vhSyuINHQhCsDKTyBmvJT1HzDHI=", + "path": "k8s.io/client-go/1.5/pkg/apimachinery/registered", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "rXeBnwLg8ZFe6m5/Ki7tELVBYDk=", + "path": "k8s.io/client-go/1.5/pkg/apis/apps", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "KzHaG858KV1tBh5cuLInNcm+G5s=", + "path": "k8s.io/client-go/1.5/pkg/apis/apps/install", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "fynWdchlRbPaxuST2oGDKiKLTqE=", + "path": "k8s.io/client-go/1.5/pkg/apis/apps/v1alpha1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "hreIYssoH4Ef/+Aglpitn3GNLR4=", + "path": "k8s.io/client-go/1.5/pkg/apis/authentication", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "EgUqJH4CqB9vXVg6T8II2OEt5LE=", + "path": "k8s.io/client-go/1.5/pkg/apis/authentication/install", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "Z3DKgomzRPGcBv/8hlL6pfnIpXI=", + "path": "k8s.io/client-go/1.5/pkg/apis/authentication/v1beta1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "GpuScB2Z+NOT4WIQg1mVvVSDUts=", + "path": "k8s.io/client-go/1.5/pkg/apis/authorization", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "+u3UD+HY9lBH+PFi/2B4W564JEw=", + "path": "k8s.io/client-go/1.5/pkg/apis/authorization/install", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "zIFzgWjmlWNLHGHMpCpDCvoLtKY=", + "path": "k8s.io/client-go/1.5/pkg/apis/authorization/v1beta1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "tdpzQFQyVkt5kCLTvtKTVqT+maE=", + "path": "k8s.io/client-go/1.5/pkg/apis/autoscaling", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "nb6LbYGS5tv8H8Ovptg6M7XuDZ4=", + "path": "k8s.io/client-go/1.5/pkg/apis/autoscaling/install", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "DNb1/nl/5RDdckRrJoXBRagzJXs=", + "path": "k8s.io/client-go/1.5/pkg/apis/autoscaling/v1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "4bLhH2vNl5l4Qp6MjLhWyWVAPE0=", + "path": "k8s.io/client-go/1.5/pkg/apis/batch", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "RpAAEynmxlvOlLLZK1KEUQRnYzk=", + "path": "k8s.io/client-go/1.5/pkg/apis/batch/install", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "uWJ2BHmjL/Gq4FFlNkqiN6vvPyM=", + "path": "k8s.io/client-go/1.5/pkg/apis/batch/v1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "mHWt/p724dKeP1vqLtWQCye7zaE=", + "path": "k8s.io/client-go/1.5/pkg/apis/batch/v2alpha1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "6dJ1dGfXkB3A42TOtMaY/rvv4N8=", + "path": "k8s.io/client-go/1.5/pkg/apis/certificates", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "Bkrhm6HbFYANwtzUE8eza9SWBk0=", + "path": "k8s.io/client-go/1.5/pkg/apis/certificates/install", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "nRRPIBQ5O3Ad24kscNtK+gPC+fk=", + "path": "k8s.io/client-go/1.5/pkg/apis/certificates/v1alpha1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "KUMhoaOg9GXHN/aAVvSLO18SgqU=", + "path": "k8s.io/client-go/1.5/pkg/apis/extensions", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "eSo2VhNAYtesvmpEPqn05goW4LY=", + "path": "k8s.io/client-go/1.5/pkg/apis/extensions/install", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "DunWIPrCC5iGMWzkaaugMOxD+hg=", + "path": "k8s.io/client-go/1.5/pkg/apis/extensions/v1beta1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "rVGYi2ko0E7vL5OZSMYX+NAGPYw=", + "path": "k8s.io/client-go/1.5/pkg/apis/policy", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "llJHd2H0LzABGB6BcletzIHnexo=", + "path": "k8s.io/client-go/1.5/pkg/apis/policy/install", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "j44bqyY13ldnuCtysYE8nRkMD7o=", + "path": "k8s.io/client-go/1.5/pkg/apis/policy/v1alpha1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "vT7rFxowcKMTYc55mddePqUFRgE=", + "path": "k8s.io/client-go/1.5/pkg/apis/rbac", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "r1MzUXsG+Zyn30aU8I5R5dgrJPA=", + "path": "k8s.io/client-go/1.5/pkg/apis/rbac/install", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "aNfO8xn8VDO3fM9CpVCe6EIB+GA=", + "path": "k8s.io/client-go/1.5/pkg/apis/rbac/v1alpha1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "rQCxrbisCXmj2wymlYG63kcTL9I=", + "path": "k8s.io/client-go/1.5/pkg/apis/storage", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "wZyxh5nt5Eh6kF7YNAIYukKWWy0=", + "path": "k8s.io/client-go/1.5/pkg/apis/storage/install", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "P8ANOt/I4Cs3QtjVXWmDA/gpQdg=", + "path": "k8s.io/client-go/1.5/pkg/apis/storage/v1beta1", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "qnVPwzvNLz2mmr3BXdU9qIhQXXU=", + "path": "k8s.io/client-go/1.5/pkg/auth/user", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "KrIchxhapSs242yAy8yrTS1XlZo=", + "path": "k8s.io/client-go/1.5/pkg/conversion", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "weZqKFcOhcnF47eDDHXzluCKSF0=", + "path": "k8s.io/client-go/1.5/pkg/conversion/queryparams", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "T3EMfyXZX5939/OOQ1JU+Nmbk4k=", + "path": "k8s.io/client-go/1.5/pkg/fields", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "2v11s3EBH8UBl2qfImT29tQN2kM=", + "path": "k8s.io/client-go/1.5/pkg/genericapiserver/openapi/common", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "GvBlph6PywK3zguou/T9kKNNdoQ=", + "path": "k8s.io/client-go/1.5/pkg/labels", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "Vtrgy827r0rWzIAgvIWY4flu740=", + "path": "k8s.io/client-go/1.5/pkg/runtime", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "SEcZqRATexhgHvDn+eHvMc07UJs=", + "path": "k8s.io/client-go/1.5/pkg/runtime/serializer", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "qzYKG9YZSj8l/W1QVTOrGAry/BM=", + "path": "k8s.io/client-go/1.5/pkg/runtime/serializer/json", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "F7h+8zZ0JPLYkac4KgSVljguBE4=", + "path": "k8s.io/client-go/1.5/pkg/runtime/serializer/protobuf", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "CvySOL8C85e3y7EWQ+Au4cwUZJM=", + "path": "k8s.io/client-go/1.5/pkg/runtime/serializer/recognizer", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "eCitoKeIun+lJzYFhAfdSIIicSM=", + "path": "k8s.io/client-go/1.5/pkg/runtime/serializer/streaming", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "kVWvZuLGltJ4YqQsiaCLRRLDDK0=", + "path": "k8s.io/client-go/1.5/pkg/runtime/serializer/versioning", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "m51+LAeQ9RK1KHX+l2iGcwbVCKs=", + "path": "k8s.io/client-go/1.5/pkg/selection", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "dp4IWcC3U6a0HeOdVCDQWODWCbw=", + "path": "k8s.io/client-go/1.5/pkg/third_party/forked/golang/reflect", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "ER898XJD1ox4d71gKZD8TLtTSpM=", + "path": "k8s.io/client-go/1.5/pkg/types", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "BVdXtnLDlmBQksRPfHOIG+qdeVg=", + "path": "k8s.io/client-go/1.5/pkg/util", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "nnh8Sa4dCupxRI4bbKaozGp1d/A=", + "path": "k8s.io/client-go/1.5/pkg/util/cert", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "S32d5uduNlwouM8+mIz+ALpliUQ=", + "path": "k8s.io/client-go/1.5/pkg/util/clock", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "Y6rWC0TUw2/uUeUjJ7kazyEUzBQ=", + "path": "k8s.io/client-go/1.5/pkg/util/errors", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "C7IfEAdCOePw3/IraaZCNXuYXLw=", + "path": "k8s.io/client-go/1.5/pkg/util/flowcontrol", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "EuslQHnhBSRXaWimYqLEqhMPV48=", + "path": "k8s.io/client-go/1.5/pkg/util/framer", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "ByO18NbZwiifFr8qtLyfJAHXguA=", + "path": "k8s.io/client-go/1.5/pkg/util/integer", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "ww+RfsoIlUBDwThg2oqC5QVz33Y=", + "path": "k8s.io/client-go/1.5/pkg/util/intstr", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "7E8f8dLlXW7u6r9sggMjvB4HEiw=", + "path": "k8s.io/client-go/1.5/pkg/util/json", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "d0pFZxMJG9j95acNmaIM1l+X+QU=", + "path": "k8s.io/client-go/1.5/pkg/util/labels", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "wCN7u1lE+25neM9jXeI7aE8EAfk=", + "path": "k8s.io/client-go/1.5/pkg/util/net", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "g+kBkxcb+tYmFtRRly+VE+JAIfw=", + "path": "k8s.io/client-go/1.5/pkg/util/parsers", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "S4wUnE5VkaWWrkLbgPL/1oNLJ4g=", + "path": "k8s.io/client-go/1.5/pkg/util/rand", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "8j9c2PqTKybtnymXbStNYRexRj8=", + "path": "k8s.io/client-go/1.5/pkg/util/runtime", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "aAz4e8hLGs0+ZAz1TdA5tY/9e1A=", + "path": "k8s.io/client-go/1.5/pkg/util/sets", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "P/fwh6QZ5tsjVyHTaASDWL3WaGs=", + "path": "k8s.io/client-go/1.5/pkg/util/uuid", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "P9Bq/1qbF4SvnN9HyCTRpbUz7sQ=", + "path": "k8s.io/client-go/1.5/pkg/util/validation", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "D0JIEjlP69cuPOZEdsSKeFgsnI8=", + "path": "k8s.io/client-go/1.5/pkg/util/validation/field", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "T7ba8t8i+BtgClMgL+aMZM94fcI=", + "path": "k8s.io/client-go/1.5/pkg/util/wait", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "6RCTv/KDiw7as4KeyrgU3XrUSQI=", + "path": "k8s.io/client-go/1.5/pkg/util/yaml", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "OwKlsSeKtz1FBVC9cQ5gWRL5pKc=", + "path": "k8s.io/client-go/1.5/pkg/version", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "Oil9WGw/dODbpBopn6LWQGS3DYg=", + "path": "k8s.io/client-go/1.5/pkg/watch", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "r5alnRCbLaPsbTeJjjTVn/bt6uw=", + "path": "k8s.io/client-go/1.5/pkg/watch/versioned", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "X1+ltyfHui/XCwDupXIf39+9gWQ=", + "path": "k8s.io/client-go/1.5/plugin/pkg/client/auth", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "KYy+js37AS0ZT08g5uBr1ZoMPmE=", + "path": "k8s.io/client-go/1.5/plugin/pkg/client/auth/gcp", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "wQ9G5++lbQpejqCzGHo037N3YcY=", + "path": "k8s.io/client-go/1.5/plugin/pkg/client/auth/oidc", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "ABe8YfZVEDoRpAUqp2BKP8o1VIA=", + "path": "k8s.io/client-go/1.5/rest", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "Gbe0Vs9hkI7X5hhbXUuWdRFffSI=", + "path": "k8s.io/client-go/1.5/tools/cache", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "K/oOznXABjqSS1c2Fs407c5F8KA=", + "path": "k8s.io/client-go/1.5/tools/clientcmd/api", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "c1PQ4WJRfpA9BYcFHW2+46hu5IE=", + "path": "k8s.io/client-go/1.5/tools/metrics", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + }, + { + "checksumSHA1": "e4W2q+6wvjejv3V0UCI1mewTTro=", + "path": "k8s.io/client-go/1.5/transport", + "revision": "c589d0c9f0d81640c518354c7bcae77d99820aa3", + "revisionTime": "2016-09-30T00:14:02Z" + } + ], + "rootPath": "github.com/prometheus/prometheus" +} diff --git a/libgo/go/cmd/go/internal/modconv/testdata/upspin.dep b/libgo/go/cmd/go/internal/modconv/testdata/upspin.dep new file mode 100644 index 00000000000..be77bcb9284 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/upspin.dep @@ -0,0 +1,57 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "bazil.org/fuse" + packages = [".","fs","fuseutil"] + revision = "371fbbdaa8987b715bdd21d6adc4c9b20155f748" + +[[projects]] + branch = "master" + name = "github.com/NYTimes/gziphandler" + packages = ["."] + revision = "97ae7fbaf81620fe97840685304a78a306a39c64" + +[[projects]] + branch = "master" + name = "github.com/golang/protobuf" + packages = ["proto"] + revision = "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + +[[projects]] + branch = "master" + name = "github.com/russross/blackfriday" + packages = ["."] + revision = "6d1ef893fcb01b4f50cb6e57ed7df3e2e627b6b2" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = ["acme","acme/autocert","hkdf"] + revision = "13931e22f9e72ea58bb73048bc752b48c6d4d4ac" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = ["context"] + revision = "4b14673ba32bee7f5ac0f990a48f033919fd418b" + +[[projects]] + branch = "master" + name = "golang.org/x/text" + packages = ["cases","internal","internal/gen","internal/tag","internal/triegen","internal/ucd","language","runes","secure/bidirule","secure/precis","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable","width"] + revision = "6eab0e8f74e86c598ec3b6fad4888e0c11482d48" + +[[projects]] + branch = "v2" + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "2246e647ba1c78b0b9f948f9fb072fff1467284fb138709c063e99736f646b90" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/libgo/go/cmd/go/internal/modconv/testdata/upspin.out b/libgo/go/cmd/go/internal/modconv/testdata/upspin.out new file mode 100644 index 00000000000..00597db8484 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/testdata/upspin.out @@ -0,0 +1,8 @@ +bazil.org/fuse 371fbbdaa8987b715bdd21d6adc4c9b20155f748 +github.com/NYTimes/gziphandler 97ae7fbaf81620fe97840685304a78a306a39c64 +github.com/golang/protobuf 1643683e1b54a9e88ad26d98f81400c8c9d9f4f9 +github.com/russross/blackfriday 6d1ef893fcb01b4f50cb6e57ed7df3e2e627b6b2 +golang.org/x/crypto 13931e22f9e72ea58bb73048bc752b48c6d4d4ac +golang.org/x/net 4b14673ba32bee7f5ac0f990a48f033919fd418b +golang.org/x/text 6eab0e8f74e86c598ec3b6fad4888e0c11482d48 +gopkg.in/yaml.v2 eb3733d160e74a9c7e442f435eb3bea458e1d19f diff --git a/libgo/go/cmd/go/internal/modconv/tsv.go b/libgo/go/cmd/go/internal/modconv/tsv.go new file mode 100644 index 00000000000..feba181e052 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/tsv.go @@ -0,0 +1,24 @@ +// 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 ( + "strings" + + "cmd/go/internal/modfile" + "cmd/go/internal/module" +) + +func ParseDependenciesTSV(file string, data []byte) (*modfile.File, error) { + mf := new(modfile.File) + for lineno, line := range strings.Split(string(data), "\n") { + lineno++ + f := strings.Split(line, "\t") + if len(f) >= 3 { + mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: f[0], Version: f[2]}}) + } + } + return mf, nil +} diff --git a/libgo/go/cmd/go/internal/modconv/vconf.go b/libgo/go/cmd/go/internal/modconv/vconf.go new file mode 100644 index 00000000000..a9a8e62518f --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/vconf.go @@ -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. + +package modconv + +import ( + "strings" + + "cmd/go/internal/modfile" + "cmd/go/internal/module" +) + +func ParseVendorConf(file string, data []byte) (*modfile.File, error) { + mf := new(modfile.File) + for lineno, line := range strings.Split(string(data), "\n") { + lineno++ + if i := strings.Index(line, "#"); i >= 0 { + line = line[:i] + } + f := strings.Fields(line) + if len(f) >= 2 { + mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: f[0], Version: f[1]}}) + } + } + return mf, nil +} diff --git a/libgo/go/cmd/go/internal/modconv/vjson.go b/libgo/go/cmd/go/internal/modconv/vjson.go new file mode 100644 index 00000000000..eec86b73398 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/vjson.go @@ -0,0 +1,29 @@ +// 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 ( + "encoding/json" + + "cmd/go/internal/modfile" + "cmd/go/internal/module" +) + +func ParseVendorJSON(file string, data []byte) (*modfile.File, error) { + var cfg struct { + Package []struct { + Path string + Revision string + } + } + if err := json.Unmarshal(data, &cfg); err != nil { + return nil, err + } + mf := new(modfile.File) + for _, d := range cfg.Package { + mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: d.Path, Version: d.Revision}}) + } + return mf, nil +} diff --git a/libgo/go/cmd/go/internal/modconv/vmanifest.go b/libgo/go/cmd/go/internal/modconv/vmanifest.go new file mode 100644 index 00000000000..c0ef2a98622 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/vmanifest.go @@ -0,0 +1,29 @@ +// 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 ( + "encoding/json" + + "cmd/go/internal/modfile" + "cmd/go/internal/module" +) + +func ParseVendorManifest(file string, data []byte) (*modfile.File, error) { + var cfg struct { + Dependencies []struct { + ImportPath string + Revision string + } + } + if err := json.Unmarshal(data, &cfg); err != nil { + return nil, err + } + mf := new(modfile.File) + for _, d := range cfg.Dependencies { + mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: d.ImportPath, Version: d.Revision}}) + } + return mf, nil +} diff --git a/libgo/go/cmd/go/internal/modconv/vyml.go b/libgo/go/cmd/go/internal/modconv/vyml.go new file mode 100644 index 00000000000..0f017a3c7a6 --- /dev/null +++ b/libgo/go/cmd/go/internal/modconv/vyml.go @@ -0,0 +1,42 @@ +// 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 ( + "strings" + + "cmd/go/internal/modfile" + "cmd/go/internal/module" +) + +func ParseVendorYML(file string, data []byte) (*modfile.File, error) { + mf := new(modfile.File) + vendors := false + path := "" + for lineno, line := range strings.Split(string(data), "\n") { + lineno++ + if line == "" { + continue + } + if strings.HasPrefix(line, "vendors:") { + vendors = true + } else if line[0] != '-' && line[0] != ' ' && line[0] != '\t' { + vendors = false + } + if !vendors { + continue + } + if strings.HasPrefix(line, "- path:") { + path = strings.TrimSpace(line[len("- path:"):]) + } + if strings.HasPrefix(line, " rev:") { + rev := strings.TrimSpace(line[len(" rev:"):]) + if path != "" && rev != "" { + mf.Require = append(mf.Require, &modfile.Require{Mod: module.Version{Path: path, Version: rev}}) + } + } + } + return mf, nil +} diff --git a/libgo/go/cmd/go/internal/modfetch/cache.go b/libgo/go/cmd/go/internal/modfetch/cache.go new file mode 100644 index 00000000000..1f9cc96c3ec --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/cache.go @@ -0,0 +1,522 @@ +// 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 ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/modfetch/codehost" + "cmd/go/internal/module" + "cmd/go/internal/par" + "cmd/go/internal/semver" +) + +var QuietLookup bool // do not print about lookups + +var PkgMod string // $GOPATH/pkg/mod; set by package modload + +func cacheDir(path string) (string, error) { + if PkgMod == "" { + return "", fmt.Errorf("internal error: modfetch.PkgMod not set") + } + enc, err := module.EncodePath(path) + if err != nil { + return "", err + } + return filepath.Join(PkgMod, "cache/download", enc, "/@v"), nil +} + +func CachePath(m module.Version, suffix string) (string, error) { + dir, err := cacheDir(m.Path) + if err != nil { + return "", err + } + if !semver.IsValid(m.Version) { + return "", fmt.Errorf("non-semver module version %q", m.Version) + } + if module.CanonicalVersion(m.Version) != m.Version { + return "", fmt.Errorf("non-canonical module version %q", m.Version) + } + encVer, err := module.EncodeVersion(m.Version) + if err != nil { + return "", err + } + return filepath.Join(dir, encVer+"."+suffix), nil +} + +func DownloadDir(m module.Version) (string, error) { + if PkgMod == "" { + return "", fmt.Errorf("internal error: modfetch.PkgMod not set") + } + enc, err := module.EncodePath(m.Path) + if err != nil { + return "", err + } + if !semver.IsValid(m.Version) { + return "", fmt.Errorf("non-semver module version %q", m.Version) + } + if module.CanonicalVersion(m.Version) != m.Version { + return "", fmt.Errorf("non-canonical module version %q", m.Version) + } + encVer, err := module.EncodeVersion(m.Version) + if err != nil { + return "", err + } + return filepath.Join(PkgMod, enc+"@"+encVer), nil +} + +// A cachingRepo is a cache around an underlying Repo, +// avoiding redundant calls to ModulePath, Versions, Stat, Latest, and GoMod (but not Zip). +// It is also safe for simultaneous use by multiple goroutines +// (so that it can be returned from Lookup multiple times). +// It serializes calls to the underlying Repo. +type cachingRepo struct { + path string + cache par.Cache // cache for all operations + r Repo +} + +func newCachingRepo(r Repo) *cachingRepo { + return &cachingRepo{ + r: r, + path: r.ModulePath(), + } +} + +func (r *cachingRepo) ModulePath() string { + return r.path +} + +func (r *cachingRepo) Versions(prefix string) ([]string, error) { + type cached struct { + list []string + err error + } + c := r.cache.Do("versions:"+prefix, func() interface{} { + list, err := r.r.Versions(prefix) + return cached{list, err} + }).(cached) + + if c.err != nil { + return nil, c.err + } + return append([]string(nil), c.list...), nil +} + +type cachedInfo struct { + info *RevInfo + err error +} + +func (r *cachingRepo) Stat(rev string) (*RevInfo, error) { + c := r.cache.Do("stat:"+rev, func() interface{} { + file, info, err := readDiskStat(r.path, rev) + if err == nil { + return cachedInfo{info, nil} + } + + if !QuietLookup { + fmt.Fprintf(os.Stderr, "go: finding %s %s\n", r.path, rev) + } + info, err = r.r.Stat(rev) + if err == nil { + if err := writeDiskStat(file, info); err != nil { + fmt.Fprintf(os.Stderr, "go: writing stat cache: %v\n", err) + } + // If we resolved, say, 1234abcde to v0.0.0-20180604122334-1234abcdef78, + // then save the information under the proper version, for future use. + if info.Version != rev { + r.cache.Do("stat:"+info.Version, func() interface{} { + return cachedInfo{info, err} + }) + } + } + return cachedInfo{info, err} + }).(cachedInfo) + + if c.err != nil { + return nil, c.err + } + info := *c.info + return &info, nil +} + +func (r *cachingRepo) Latest() (*RevInfo, error) { + c := r.cache.Do("latest:", func() interface{} { + if !QuietLookup { + fmt.Fprintf(os.Stderr, "go: finding %s latest\n", r.path) + } + info, err := r.r.Latest() + + // Save info for likely future Stat call. + if err == nil { + r.cache.Do("stat:"+info.Version, func() interface{} { + return cachedInfo{info, err} + }) + if file, _, err := readDiskStat(r.path, info.Version); err != nil { + writeDiskStat(file, info) + } + } + + return cachedInfo{info, err} + }).(cachedInfo) + + if c.err != nil { + return nil, c.err + } + info := *c.info + return &info, nil +} + +func (r *cachingRepo) GoMod(rev string) ([]byte, error) { + type cached struct { + text []byte + err error + } + c := r.cache.Do("gomod:"+rev, func() interface{} { + file, text, err := readDiskGoMod(r.path, rev) + if err == nil { + // Note: readDiskGoMod already called checkGoMod. + return cached{text, nil} + } + + // Convert rev to canonical version + // so that we use the right identifier in the go.sum check. + info, err := r.Stat(rev) + if err != nil { + return cached{nil, err} + } + rev = info.Version + + text, err = r.r.GoMod(rev) + if err == nil { + checkGoMod(r.path, rev, text) + if err := writeDiskGoMod(file, text); err != nil { + fmt.Fprintf(os.Stderr, "go: writing go.mod cache: %v\n", err) + } + } + return cached{text, err} + }).(cached) + + if c.err != nil { + return nil, c.err + } + return append([]byte(nil), c.text...), nil +} + +func (r *cachingRepo) Zip(version, tmpdir string) (string, error) { + return r.r.Zip(version, tmpdir) +} + +// Stat is like Lookup(path).Stat(rev) but avoids the +// repository path resolution in Lookup if the result is +// already cached on local disk. +func Stat(path, rev string) (*RevInfo, error) { + _, info, err := readDiskStat(path, rev) + if err == nil { + return info, nil + } + repo, err := Lookup(path) + if err != nil { + return nil, err + } + return repo.Stat(rev) +} + +// InfoFile is like Stat but returns the name of the file containing +// the cached information. +func InfoFile(path, version string) (string, error) { + if !semver.IsValid(version) { + return "", fmt.Errorf("invalid version %q", version) + } + if _, err := Stat(path, version); err != nil { + return "", err + } + // Stat should have populated the disk cache for us. + file, _, err := readDiskStat(path, version) + if err != nil { + return "", err + } + return file, nil +} + +// GoMod is like Lookup(path).GoMod(rev) but avoids the +// repository path resolution in Lookup if the result is +// already cached on local disk. +func GoMod(path, rev string) ([]byte, error) { + // Convert commit hash to pseudo-version + // to increase cache hit rate. + if !semver.IsValid(rev) { + info, err := Stat(path, rev) + if err != nil { + return nil, err + } + rev = info.Version + } + _, data, err := readDiskGoMod(path, rev) + if err == nil { + return data, nil + } + repo, err := Lookup(path) + if err != nil { + return nil, err + } + return repo.GoMod(rev) +} + +// GoModFile is like GoMod but returns the name of the file containing +// the cached information. +func GoModFile(path, version string) (string, error) { + if !semver.IsValid(version) { + return "", fmt.Errorf("invalid version %q", version) + } + if _, err := GoMod(path, version); err != nil { + return "", err + } + // GoMod should have populated the disk cache for us. + file, _, err := readDiskGoMod(path, version) + if err != nil { + return "", err + } + return file, nil +} + +// GoModSum returns the go.sum entry for the module version's go.mod file. +// (That is, it returns the entry listed in go.sum as "path version/go.mod".) +func GoModSum(path, version string) (string, error) { + if !semver.IsValid(version) { + return "", fmt.Errorf("invalid version %q", version) + } + data, err := GoMod(path, version) + if err != nil { + return "", err + } + sum, err := goModSum(data) + if err != nil { + return "", err + } + return sum, nil +} + +var errNotCached = fmt.Errorf("not in cache") + +// readDiskStat reads a cached stat result from disk, +// returning the name of the cache file and the result. +// If the read fails, the caller can use +// writeDiskStat(file, info) to write a new cache entry. +func readDiskStat(path, rev string) (file string, info *RevInfo, err error) { + file, data, err := readDiskCache(path, rev, "info") + if err != nil { + if file, info, err := readDiskStatByHash(path, rev); err == nil { + return file, info, nil + } + return file, nil, err + } + info = new(RevInfo) + if err := json.Unmarshal(data, info); err != nil { + return file, nil, errNotCached + } + // The disk might have stale .info files that have Name and Short fields set. + // We want to canonicalize to .info files with those fields omitted. + // Remarshal and update the cache file if needed. + data2, err := json.Marshal(info) + if err == nil && !bytes.Equal(data2, data) { + writeDiskCache(file, data) + } + return file, info, nil +} + +// readDiskStatByHash is a fallback for readDiskStat for the case +// where rev is a commit hash instead of a proper semantic version. +// In that case, we look for a cached pseudo-version that matches +// the commit hash. If we find one, we use it. +// This matters most for converting legacy package management +// configs, when we are often looking up commits by full hash. +// Without this check we'd be doing network I/O to the remote repo +// just to find out about a commit we already know about +// (and have cached under its pseudo-version). +func readDiskStatByHash(path, rev string) (file string, info *RevInfo, err error) { + if PkgMod == "" { + // Do not download to current directory. + return "", nil, errNotCached + } + + if !codehost.AllHex(rev) || len(rev) < 12 { + return "", nil, errNotCached + } + rev = rev[:12] + cdir, err := cacheDir(path) + if err != nil { + return "", nil, errNotCached + } + dir, err := os.Open(cdir) + if err != nil { + return "", nil, errNotCached + } + names, err := dir.Readdirnames(-1) + dir.Close() + if err != nil { + return "", nil, errNotCached + } + suffix := "-" + rev + ".info" + for _, name := range names { + if strings.HasSuffix(name, suffix) && IsPseudoVersion(strings.TrimSuffix(name, ".info")) { + return readDiskStat(path, strings.TrimSuffix(name, ".info")) + } + } + return "", nil, errNotCached +} + +// oldVgoPrefix is the prefix in the old auto-generated cached go.mod files. +// We stopped trying to auto-generate the go.mod files. Now we use a trivial +// go.mod with only a module line, and we've dropped the version prefix +// entirely. If we see a version prefix, that means we're looking at an old copy +// and should ignore it. +var oldVgoPrefix = []byte("//vgo 0.0.") + +// readDiskGoMod reads a cached stat result from disk, +// returning the name of the cache file and the result. +// If the read fails, the caller can use +// writeDiskGoMod(file, data) to write a new cache entry. +func readDiskGoMod(path, rev string) (file string, data []byte, err error) { + file, data, err = readDiskCache(path, rev, "mod") + + // If the file has an old auto-conversion prefix, pretend it's not there. + if bytes.HasPrefix(data, oldVgoPrefix) { + err = errNotCached + data = nil + } + + if err == nil { + checkGoMod(path, rev, data) + } + + return file, data, err +} + +// readDiskCache is the generic "read from a cache file" implementation. +// It takes the revision and an identifying suffix for the kind of data being cached. +// It returns the name of the cache file and the content of the file. +// If the read fails, the caller can use +// writeDiskCache(file, data) to write a new cache entry. +func readDiskCache(path, rev, suffix string) (file string, data []byte, err error) { + file, err = CachePath(module.Version{Path: path, Version: rev}, suffix) + if err != nil { + return "", nil, errNotCached + } + data, err = ioutil.ReadFile(file) + if err != nil { + return file, nil, errNotCached + } + return file, data, nil +} + +// writeDiskStat writes a stat result cache entry. +// The file name must have been returned by a previous call to readDiskStat. +func writeDiskStat(file string, info *RevInfo) error { + if file == "" { + return nil + } + js, err := json.Marshal(info) + if err != nil { + return err + } + return writeDiskCache(file, js) +} + +// writeDiskGoMod writes a go.mod cache entry. +// The file name must have been returned by a previous call to readDiskGoMod. +func writeDiskGoMod(file string, text []byte) error { + return writeDiskCache(file, text) +} + +// writeDiskCache is the generic "write to a cache file" implementation. +// The file must have been returned by a previous call to readDiskCache. +func writeDiskCache(file string, data []byte) error { + if file == "" { + return nil + } + // Make sure directory for file exists. + if err := os.MkdirAll(filepath.Dir(file), 0777); err != nil { + return err + } + // Write data to temp file next to target file. + f, err := ioutil.TempFile(filepath.Dir(file), filepath.Base(file)+".tmp-") + if err != nil { + return err + } + defer os.Remove(f.Name()) + defer f.Close() + if _, err := f.Write(data); err != nil { + return err + } + if err := f.Close(); err != nil { + return err + } + // Rename temp file onto cache file, + // so that the cache file is always a complete file. + if err := os.Rename(f.Name(), file); err != nil { + return err + } + + if strings.HasSuffix(file, ".mod") { + rewriteVersionList(filepath.Dir(file)) + } + return nil +} + +// rewriteVersionList rewrites the version list in dir +// after a new *.mod file has been written. +func rewriteVersionList(dir string) { + if filepath.Base(dir) != "@v" { + base.Fatalf("go: internal error: misuse of rewriteVersionList") + } + + // TODO(rsc): We should do some kind of directory locking here, + // to avoid lost updates. + + infos, err := ioutil.ReadDir(dir) + if err != nil { + return + } + var list []string + for _, info := range infos { + // We look for *.mod files on the theory that if we can't supply + // the .mod file then there's no point in listing that version, + // since it's unusable. (We can have *.info without *.mod.) + // We don't require *.zip files on the theory that for code only + // involved in module graph construction, many *.zip files + // will never be requested. + name := info.Name() + if strings.HasSuffix(name, ".mod") { + v := strings.TrimSuffix(name, ".mod") + if v != "" && module.CanonicalVersion(v) == v { + list = append(list, v) + } + } + } + SortVersions(list) + + var buf bytes.Buffer + for _, v := range list { + buf.WriteString(v) + buf.WriteString("\n") + } + listFile := filepath.Join(dir, "list") + old, _ := ioutil.ReadFile(listFile) + if bytes.Equal(buf.Bytes(), old) { + return + } + // TODO: Use rename to install file, + // so that readers never see an incomplete file. + ioutil.WriteFile(listFile, buf.Bytes(), 0666) +} diff --git a/libgo/go/cmd/go/internal/modfetch/cache_test.go b/libgo/go/cmd/go/internal/modfetch/cache_test.go new file mode 100644 index 00000000000..241c800e692 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/cache_test.go @@ -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. + +package modfetch + +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +func TestWriteDiskCache(t *testing.T) { + tmpdir, err := ioutil.TempDir("", "go-writeCache-test-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + err = writeDiskCache(filepath.Join(tmpdir, "file"), []byte("data")) + if err != nil { + t.Fatal(err) + } +} diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/codehost.go b/libgo/go/cmd/go/internal/modfetch/codehost/codehost.go new file mode 100644 index 00000000000..4103ddc717f --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/codehost/codehost.go @@ -0,0 +1,266 @@ +// 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 codehost defines the interface implemented by a code hosting source, +// along with support code for use by implementations. +package codehost + +import ( + "bytes" + "crypto/sha256" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "sync" + "time" + + "cmd/go/internal/cfg" + "cmd/go/internal/str" +) + +// Downloaded size limits. +const ( + MaxGoMod = 16 << 20 // maximum size of go.mod file + MaxLICENSE = 16 << 20 // maximum size of LICENSE file + MaxZipFile = 500 << 20 // maximum size of downloaded zip file +) + +// A Repo represents a code hosting source. +// Typical implementations include local version control repositories, +// remote version control servers, and code hosting sites. +// A Repo must be safe for simultaneous use by multiple goroutines. +type Repo interface { + // List lists all tags with the given prefix. + Tags(prefix string) (tags []string, err error) + + // Stat returns information about the revision rev. + // A revision can be any identifier known to the underlying service: + // commit hash, branch, tag, and so on. + Stat(rev string) (*RevInfo, error) + + // Latest returns the latest revision on the default branch, + // whatever that means in the underlying implementation. + Latest() (*RevInfo, error) + + // ReadFile reads the given file in the file tree corresponding to revision rev. + // It should refuse to read more than maxSize bytes. + // + // If the requested file does not exist it should return an error for which + // os.IsNotExist(err) returns true. + ReadFile(rev, file string, maxSize int64) (data []byte, err error) + + // ReadFileRevs reads a single file at multiple versions. + // It should refuse to read more than maxSize bytes. + // The result is a map from each requested rev strings + // to the associated FileRev. The map must have a non-nil + // entry for every requested rev (unless ReadFileRevs returned an error). + // A file simply being missing or even corrupted in revs[i] + // should be reported only in files[revs[i]].Err, not in the error result + // from ReadFileRevs. + // The overall call should return an error (and no map) only + // in the case of a problem with obtaining the data, such as + // a network failure. + // Implementations may assume that revs only contain tags, + // not direct commit hashes. + ReadFileRevs(revs []string, file string, maxSize int64) (files map[string]*FileRev, err error) + + // ReadZip downloads a zip file for the subdir subdirectory + // of the given revision to a new file in a given temporary directory. + // It should refuse to read more than maxSize bytes. + // It returns a ReadCloser for a streamed copy of the zip file, + // along with the actual subdirectory (possibly shorter than subdir) + // contained in the zip file. All files in the zip file are expected to be + // nested in a single top-level directory, whose name is not specified. + ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser, actualSubdir string, err error) + + // RecentTag returns the most recent tag at or before the given rev + // with the given prefix. It should make a best-effort attempt to + // find a tag that is a valid semantic version (following the prefix), + // or else the result is not useful to the caller, but it need not + // incur great expense in doing so. For example, the git implementation + // of RecentTag limits git's search to tags matching the glob expression + // "v[0-9]*.[0-9]*.[0-9]*" (after the prefix). + RecentTag(rev, prefix string) (tag string, err error) +} + +// A Rev describes a single revision in a source code repository. +type RevInfo struct { + Name string // complete ID in underlying repository + Short string // shortened ID, for use in pseudo-version + Version string // version used in lookup + Time time.Time // commit time + Tags []string // known tags for commit +} + +// A FileRev describes the result of reading a file at a given revision. +type FileRev struct { + Rev string // requested revision + Data []byte // file data + Err error // error if any; os.IsNotExist(Err)==true if rev exists but file does not exist in that rev +} + +// AllHex reports whether the revision rev is entirely lower-case hexadecimal digits. +func AllHex(rev string) bool { + for i := 0; i < len(rev); i++ { + c := rev[i] + if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' { + continue + } + return false + } + return true +} + +// ShortenSHA1 shortens a SHA1 hash (40 hex digits) to the canonical length +// used in pseudo-versions (12 hex digits). +func ShortenSHA1(rev string) string { + if AllHex(rev) && len(rev) == 40 { + return rev[:12] + } + return rev +} + +// WorkRoot is the root of the cached work directory. +// It is set by cmd/go/internal/modload.InitMod. +var WorkRoot string + +// WorkDir returns the name of the cached work directory to use for the +// given repository type and name. +func WorkDir(typ, name string) (string, error) { + if WorkRoot == "" { + return "", fmt.Errorf("codehost.WorkRoot not set") + } + + // We name the work directory for the SHA256 hash of the type and name. + // We intentionally avoid the actual name both because of possible + // conflicts with valid file system paths and because we want to ensure + // that one checkout is never nested inside another. That nesting has + // led to security problems in the past. + if strings.Contains(typ, ":") { + return "", fmt.Errorf("codehost.WorkDir: type cannot contain colon") + } + key := typ + ":" + name + dir := filepath.Join(WorkRoot, fmt.Sprintf("%x", sha256.Sum256([]byte(key)))) + data, err := ioutil.ReadFile(dir + ".info") + info, err2 := os.Stat(dir) + if err == nil && err2 == nil && info.IsDir() { + // Info file and directory both already exist: reuse. + have := strings.TrimSuffix(string(data), "\n") + if have != key { + return "", fmt.Errorf("%s exists with wrong content (have %q want %q)", dir+".info", have, key) + } + if cfg.BuildX { + fmt.Fprintf(os.Stderr, "# %s for %s %s\n", dir, typ, name) + } + return dir, nil + } + + // Info file or directory missing. Start from scratch. + if cfg.BuildX { + fmt.Fprintf(os.Stderr, "mkdir -p %s # %s %s\n", dir, typ, name) + } + os.RemoveAll(dir) + if err := os.MkdirAll(dir, 0777); err != nil { + return "", err + } + if err := ioutil.WriteFile(dir+".info", []byte(key), 0666); err != nil { + os.RemoveAll(dir) + return "", err + } + return dir, nil +} + +type RunError struct { + Cmd string + Err error + Stderr []byte +} + +func (e *RunError) Error() string { + text := e.Cmd + ": " + e.Err.Error() + stderr := bytes.TrimRight(e.Stderr, "\n") + if len(stderr) > 0 { + text += ":\n\t" + strings.Replace(string(stderr), "\n", "\n\t", -1) + } + return text +} + +var dirLock sync.Map + +// Run runs the command line in the given directory +// (an empty dir means the current directory). +// It returns the standard output and, for a non-zero exit, +// a *RunError indicating the command, exit status, and standard error. +// Standard error is unavailable for commands that exit successfully. +func Run(dir string, cmdline ...interface{}) ([]byte, error) { + return RunWithStdin(dir, nil, cmdline...) +} + +// bashQuoter escapes characters that have special meaning in double-quoted strings in the bash shell. +// See https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html. +var bashQuoter = strings.NewReplacer(`"`, `\"`, `$`, `\$`, "`", "\\`", `\`, `\\`) + +func RunWithStdin(dir string, stdin io.Reader, cmdline ...interface{}) ([]byte, error) { + if dir != "" { + muIface, ok := dirLock.Load(dir) + if !ok { + muIface, _ = dirLock.LoadOrStore(dir, new(sync.Mutex)) + } + mu := muIface.(*sync.Mutex) + mu.Lock() + defer mu.Unlock() + } + + cmd := str.StringList(cmdline...) + if cfg.BuildX { + text := new(strings.Builder) + if dir != "" { + text.WriteString("cd ") + text.WriteString(dir) + text.WriteString("; ") + } + for i, arg := range cmd { + if i > 0 { + text.WriteByte(' ') + } + switch { + case strings.ContainsAny(arg, "'"): + // Quote args that could be mistaken for quoted args. + text.WriteByte('"') + text.WriteString(bashQuoter.Replace(arg)) + text.WriteByte('"') + case strings.ContainsAny(arg, "$`\\*?[\"\t\n\v\f\r \u0085\u00a0"): + // Quote args that contain special characters, glob patterns, or spaces. + text.WriteByte('\'') + text.WriteString(arg) + text.WriteByte('\'') + default: + text.WriteString(arg) + } + } + fmt.Fprintf(os.Stderr, "%s\n", text) + start := time.Now() + defer func() { + fmt.Fprintf(os.Stderr, "%.3fs # %s\n", time.Since(start).Seconds(), text) + }() + } + // TODO: Impose limits on command output size. + // TODO: Set environment to get English error messages. + var stderr bytes.Buffer + var stdout bytes.Buffer + c := exec.Command(cmd[0], cmd[1:]...) + c.Dir = dir + c.Stdin = stdin + c.Stderr = &stderr + c.Stdout = &stdout + err := c.Run() + if err != nil { + err = &RunError{Cmd: strings.Join(cmd, " ") + " in " + dir, Stderr: stderr.Bytes(), Err: err} + } + return stdout.Bytes(), err +} diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/git.go b/libgo/go/cmd/go/internal/modfetch/codehost/git.go new file mode 100644 index 00000000000..87940a8f02c --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/codehost/git.go @@ -0,0 +1,711 @@ +// 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 codehost + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "sort" + "strconv" + "strings" + "sync" + "time" + + "cmd/go/internal/par" +) + +// GitRepo returns the code repository at the given Git remote reference. +func GitRepo(remote string) (Repo, error) { + return newGitRepoCached(remote, false) +} + +// LocalGitRepo is like Repo but accepts both Git remote references +// and paths to repositories on the local file system. +func LocalGitRepo(remote string) (Repo, error) { + return newGitRepoCached(remote, true) +} + +const gitWorkDirType = "git2" + +var gitRepoCache par.Cache + +func newGitRepoCached(remote string, localOK bool) (Repo, error) { + type key struct { + remote string + localOK bool + } + type cached struct { + repo Repo + err error + } + + c := gitRepoCache.Do(key{remote, localOK}, func() interface{} { + repo, err := newGitRepo(remote, localOK) + return cached{repo, err} + }).(cached) + + return c.repo, c.err +} + +func newGitRepo(remote string, localOK bool) (Repo, error) { + r := &gitRepo{remote: remote} + if strings.Contains(remote, "://") { + // This is a remote path. + dir, err := WorkDir(gitWorkDirType, r.remote) + if err != nil { + return nil, err + } + r.dir = dir + if _, err := os.Stat(filepath.Join(dir, "objects")); err != nil { + if _, err := Run(dir, "git", "init", "--bare"); err != nil { + os.RemoveAll(dir) + return nil, err + } + // We could just say git fetch https://whatever later, + // but this lets us say git fetch origin instead, which + // is a little nicer. More importantly, using a named remote + // avoids a problem with Git LFS. See golang.org/issue/25605. + if _, err := Run(dir, "git", "remote", "add", "origin", r.remote); err != nil { + os.RemoveAll(dir) + return nil, err + } + r.remote = "origin" + } + } else { + // Local path. + // Disallow colon (not in ://) because sometimes + // that's rcp-style host:path syntax and sometimes it's not (c:\work). + // The go command has always insisted on URL syntax for ssh. + if strings.Contains(remote, ":") { + return nil, fmt.Errorf("git remote cannot use host:path syntax") + } + if !localOK { + return nil, fmt.Errorf("git remote must not be local directory") + } + r.local = true + info, err := os.Stat(remote) + if err != nil { + return nil, err + } + if !info.IsDir() { + return nil, fmt.Errorf("%s exists but is not a directory", remote) + } + r.dir = remote + } + return r, nil +} + +type gitRepo struct { + remote string + local bool + dir string + + mu sync.Mutex // protects fetchLevel, some git repo state + fetchLevel int + + statCache par.Cache + + refsOnce sync.Once + refs map[string]string + refsErr error + + localTagsOnce sync.Once + localTags map[string]bool +} + +const ( + // How much have we fetched into the git repo (in this process)? + fetchNone = iota // nothing yet + fetchSome // shallow fetches of individual hashes + fetchAll // "fetch -t origin": get all remote branches and tags +) + +// loadLocalTags loads tag references from the local git cache +// into the map r.localTags. +// Should only be called as r.localTagsOnce.Do(r.loadLocalTags). +func (r *gitRepo) loadLocalTags() { + // The git protocol sends all known refs and ls-remote filters them on the client side, + // so we might as well record both heads and tags in one shot. + // Most of the time we only care about tags but sometimes we care about heads too. + out, err := Run(r.dir, "git", "tag", "-l") + if err != nil { + return + } + + r.localTags = make(map[string]bool) + for _, line := range strings.Split(string(out), "\n") { + if line != "" { + r.localTags[line] = true + } + } +} + +// loadRefs loads heads and tags references from the remote into the map r.refs. +// Should only be called as r.refsOnce.Do(r.loadRefs). +func (r *gitRepo) loadRefs() { + // The git protocol sends all known refs and ls-remote filters them on the client side, + // so we might as well record both heads and tags in one shot. + // Most of the time we only care about tags but sometimes we care about heads too. + out, err := Run(r.dir, "git", "ls-remote", "-q", r.remote) + if err != nil { + r.refsErr = err + return + } + + r.refs = make(map[string]string) + for _, line := range strings.Split(string(out), "\n") { + f := strings.Fields(line) + if len(f) != 2 { + continue + } + if f[1] == "HEAD" || strings.HasPrefix(f[1], "refs/heads/") || strings.HasPrefix(f[1], "refs/tags/") { + r.refs[f[1]] = f[0] + } + } + for ref, hash := range r.refs { + if strings.HasSuffix(ref, "^{}") { // record unwrapped annotated tag as value of tag + r.refs[strings.TrimSuffix(ref, "^{}")] = hash + delete(r.refs, ref) + } + } +} + +func (r *gitRepo) Tags(prefix string) ([]string, error) { + r.refsOnce.Do(r.loadRefs) + if r.refsErr != nil { + return nil, r.refsErr + } + + tags := []string{} + for ref := range r.refs { + if !strings.HasPrefix(ref, "refs/tags/") { + continue + } + tag := ref[len("refs/tags/"):] + if !strings.HasPrefix(tag, prefix) { + continue + } + tags = append(tags, tag) + } + sort.Strings(tags) + return tags, nil +} + +func (r *gitRepo) Latest() (*RevInfo, error) { + r.refsOnce.Do(r.loadRefs) + if r.refsErr != nil { + return nil, r.refsErr + } + if r.refs["HEAD"] == "" { + return nil, fmt.Errorf("no commits") + } + return r.Stat(r.refs["HEAD"]) +} + +// findRef finds some ref name for the given hash, +// for use when the server requires giving a ref instead of a hash. +// There may be multiple ref names for a given hash, +// in which case this returns some name - it doesn't matter which. +func (r *gitRepo) findRef(hash string) (ref string, ok bool) { + r.refsOnce.Do(r.loadRefs) + for ref, h := range r.refs { + if h == hash { + return ref, true + } + } + return "", false +} + +func unshallow(gitDir string) []string { + if _, err := os.Stat(filepath.Join(gitDir, "shallow")); err == nil { + return []string{"--unshallow"} + } + return []string{} +} + +// minHashDigits is the minimum number of digits to require +// before accepting a hex digit sequence as potentially identifying +// a specific commit in a git repo. (Of course, users can always +// specify more digits, and many will paste in all 40 digits, +// but many of git's commands default to printing short hashes +// as 7 digits.) +const minHashDigits = 7 + +// stat stats the given rev in the local repository, +// or else it fetches more info from the remote repository and tries again. +func (r *gitRepo) stat(rev string) (*RevInfo, error) { + if r.local { + return r.statLocal(rev, rev) + } + + // Fast path: maybe rev is a hash we already have locally. + didStatLocal := false + if len(rev) >= minHashDigits && len(rev) <= 40 && AllHex(rev) { + if info, err := r.statLocal(rev, rev); err == nil { + return info, nil + } + didStatLocal = true + } + + // Maybe rev is a tag we already have locally. + // (Note that we're excluding branches, which can be stale.) + r.localTagsOnce.Do(r.loadLocalTags) + if r.localTags[rev] { + return r.statLocal(rev, "refs/tags/"+rev) + } + + // Maybe rev is the name of a tag or branch on the remote server. + // 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) + var ref, hash string + if r.refs["refs/tags/"+rev] != "" { + ref = "refs/tags/" + rev + hash = r.refs[ref] + // Keep rev as is: tags are assumed not to change meaning. + } else if r.refs["refs/heads/"+rev] != "" { + ref = "refs/heads/" + rev + hash = r.refs[ref] + rev = hash // Replace rev, because meaning of refs/heads/foo can change. + } else if rev == "HEAD" && r.refs["HEAD"] != "" { + ref = "HEAD" + hash = r.refs[ref] + rev = hash // Replace rev, because meaning of HEAD can change. + } else if len(rev) >= minHashDigits && len(rev) <= 40 && AllHex(rev) { + // At the least, we have a hash prefix we can look up after the fetch below. + // Maybe we can map it to a full hash using the known refs. + prefix := rev + // Check whether rev is prefix of known ref hash. + for k, h := range r.refs { + if strings.HasPrefix(h, prefix) { + if hash != "" && hash != h { + // Hash is an ambiguous hash prefix. + // More information will not change that. + return nil, fmt.Errorf("ambiguous revision %s", rev) + } + if ref == "" || ref > k { // Break ties deterministically when multiple refs point at same hash. + ref = k + } + rev = h + hash = h + } + } + if hash == "" && len(rev) == 40 { // Didn't find a ref, but rev is a full hash. + hash = rev + } + } else { + return nil, fmt.Errorf("unknown revision %s", rev) + } + + // Protect r.fetchLevel and the "fetch more and more" sequence. + // TODO(rsc): Add LockDir and use it for protecting that + // sequence, so that multiple processes don't collide in their + // git commands. + r.mu.Lock() + defer r.mu.Unlock() + + // Perhaps r.localTags did not have the ref when we loaded local tags, + // but we've since done fetches that pulled down the hash we need + // (or already have the hash we need, just without its tag). + // Either way, try a local stat before falling back to network I/O. + if !didStatLocal { + if info, err := r.statLocal(rev, hash); err == nil { + if strings.HasPrefix(ref, "refs/tags/") { + // Make sure tag exists, so it will be in localTags next time the go command is run. + Run(r.dir, "git", "tag", strings.TrimPrefix(ref, "refs/tags/"), hash) + } + return info, nil + } + } + + // If we know a specific commit we need, fetch it. + if r.fetchLevel <= fetchSome && hash != "" && !r.local { + r.fetchLevel = fetchSome + var refspec string + if ref != "" && ref != "HEAD" { + // If we do know the ref name, save the mapping locally + // so that (if it is a tag) it can show up in localTags + // on a future call. Also, some servers refuse to allow + // full hashes in ref specs, so prefer a ref name if known. + refspec = ref + ":" + ref + } else { + // Fetch the hash but give it a local name (refs/dummy), + // because that triggers the fetch behavior of creating any + // other known remote tags for the hash. We never use + // refs/dummy (it's not refs/tags/dummy) and it will be + // overwritten in the next command, and that's fine. + ref = hash + refspec = hash + ":refs/dummy" + } + _, err := Run(r.dir, "git", "fetch", "-f", "--depth=1", r.remote, refspec) + if err == nil { + return r.statLocal(rev, ref) + } + // Don't try to be smart about parsing the error. + // It's too complex and varies too much by git version. + // No matter what went wrong, fall back to a complete fetch. + } + + // Last resort. + // Fetch all heads and tags and hope the hash we want is in the history. + if r.fetchLevel < fetchAll { + // TODO(bcmills): should we wait to upgrade fetchLevel until after we check + // err? If there is a temporary server error, we want subsequent fetches to + // try again instead of proceeding with an incomplete repo. + r.fetchLevel = fetchAll + if err := r.fetchUnshallow("refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil { + return nil, err + } + } + + return r.statLocal(rev, rev) +} + +func (r *gitRepo) fetchUnshallow(refSpecs ...string) error { + // To work around a protocol version 2 bug that breaks --unshallow, + // add -c protocol.version=0. + // TODO(rsc): The bug is believed to be server-side, meaning only + // on Google's Git servers. Once the servers are fixed, drop the + // protocol.version=0. See Google-internal bug b/110495752. + var protoFlag []string + unshallowFlag := unshallow(r.dir) + if len(unshallowFlag) > 0 { + protoFlag = []string{"-c", "protocol.version=0"} + } + _, err := Run(r.dir, "git", protoFlag, "fetch", unshallowFlag, "-f", r.remote, refSpecs) + return err +} + +// statLocal returns a RevInfo describing rev in the local git repository. +// It uses version as info.Version. +func (r *gitRepo) statLocal(version, rev string) (*RevInfo, error) { + out, err := Run(r.dir, "git", "-c", "log.showsignature=false", "log", "-n1", "--format=format:%H %ct %D", rev) + if err != nil { + return nil, fmt.Errorf("unknown revision %s", rev) + } + f := strings.Fields(string(out)) + if len(f) < 2 { + return nil, fmt.Errorf("unexpected response from git log: %q", out) + } + hash := f[0] + if strings.HasPrefix(hash, version) { + version = hash // extend to full hash + } + t, err := strconv.ParseInt(f[1], 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid time from git log: %q", out) + } + + info := &RevInfo{ + Name: hash, + Short: ShortenSHA1(hash), + Time: time.Unix(t, 0).UTC(), + Version: hash, + } + + // Add tags. Output looks like: + // ede458df7cd0fdca520df19a33158086a8a68e81 1523994202 HEAD -> master, tag: v1.2.4-annotated, tag: v1.2.3, origin/master, origin/HEAD + for i := 2; i < len(f); i++ { + if f[i] == "tag:" { + i++ + if i < len(f) { + info.Tags = append(info.Tags, strings.TrimSuffix(f[i], ",")) + } + } + } + sort.Strings(info.Tags) + + // Used hash as info.Version above. + // Use caller's suggested version if it appears in the tag list + // (filters out branch names, HEAD). + for _, tag := range info.Tags { + if version == tag { + info.Version = version + } + } + + return info, nil +} + +func (r *gitRepo) Stat(rev string) (*RevInfo, error) { + if rev == "latest" { + return r.Latest() + } + type cached struct { + info *RevInfo + err error + } + c := r.statCache.Do(rev, func() interface{} { + info, err := r.stat(rev) + return cached{info, err} + }).(cached) + return c.info, c.err +} + +func (r *gitRepo) ReadFile(rev, file string, maxSize int64) ([]byte, error) { + // TODO: Could use git cat-file --batch. + info, err := r.Stat(rev) // download rev into local git repo + if err != nil { + return nil, err + } + out, err := Run(r.dir, "git", "cat-file", "blob", info.Name+":"+file) + if err != nil { + return nil, os.ErrNotExist + } + return out, nil +} + +func (r *gitRepo) ReadFileRevs(revs []string, file string, maxSize int64) (map[string]*FileRev, error) { + // Create space to hold results. + files := make(map[string]*FileRev) + for _, rev := range revs { + f := &FileRev{Rev: rev} + files[rev] = f + } + + // Collect locally-known revs. + need, err := r.readFileRevs(revs, file, files) + if err != nil { + return nil, err + } + if len(need) == 0 { + return files, nil + } + + // Build list of known remote refs that might help. + var redo []string + r.refsOnce.Do(r.loadRefs) + if r.refsErr != nil { + return nil, r.refsErr + } + for _, tag := range need { + if r.refs["refs/tags/"+tag] != "" { + redo = append(redo, tag) + } + } + if len(redo) == 0 { + return files, nil + } + + // Protect r.fetchLevel and the "fetch more and more" sequence. + // See stat method above. + r.mu.Lock() + defer r.mu.Unlock() + + var refs []string + var protoFlag []string + var unshallowFlag []string + for _, tag := range redo { + refs = append(refs, "refs/tags/"+tag+":refs/tags/"+tag) + } + if len(refs) > 1 { + unshallowFlag = unshallow(r.dir) + if len(unshallowFlag) > 0 { + // To work around a protocol version 2 bug that breaks --unshallow, + // add -c protocol.version=0. + // TODO(rsc): The bug is believed to be server-side, meaning only + // on Google's Git servers. Once the servers are fixed, drop the + // protocol.version=0. See Google-internal bug b/110495752. + protoFlag = []string{"-c", "protocol.version=0"} + } + } + if _, err := Run(r.dir, "git", protoFlag, "fetch", unshallowFlag, "-f", r.remote, refs); err != nil { + return nil, err + } + + // TODO(bcmills): after the 1.11 freeze, replace the block above with: + // if r.fetchLevel <= fetchSome { + // r.fetchLevel = fetchSome + // var refs []string + // for _, tag := range redo { + // refs = append(refs, "refs/tags/"+tag+":refs/tags/"+tag) + // } + // if _, err := Run(r.dir, "git", "fetch", "--update-shallow", "-f", r.remote, refs); err != nil { + // return nil, err + // } + // } + + if _, err := r.readFileRevs(redo, file, files); err != nil { + return nil, err + } + + return files, nil +} + +func (r *gitRepo) readFileRevs(tags []string, file string, fileMap map[string]*FileRev) (missing []string, err error) { + var stdin bytes.Buffer + for _, tag := range tags { + fmt.Fprintf(&stdin, "refs/tags/%s\n", tag) + fmt.Fprintf(&stdin, "refs/tags/%s:%s\n", tag, file) + } + + data, err := RunWithStdin(r.dir, &stdin, "git", "cat-file", "--batch") + if err != nil { + return nil, err + } + + next := func() (typ string, body []byte, ok bool) { + var line string + i := bytes.IndexByte(data, '\n') + if i < 0 { + return "", nil, false + } + line, data = string(bytes.TrimSpace(data[:i])), data[i+1:] + if strings.HasSuffix(line, " missing") { + return "missing", nil, true + } + f := strings.Fields(line) + if len(f) != 3 { + return "", nil, false + } + n, err := strconv.Atoi(f[2]) + if err != nil || n > len(data) { + return "", nil, false + } + body, data = data[:n], data[n:] + if len(data) > 0 && data[0] == '\r' { + data = data[1:] + } + if len(data) > 0 && data[0] == '\n' { + data = data[1:] + } + return f[1], body, true + } + + badGit := func() ([]string, error) { + return nil, fmt.Errorf("malformed output from git cat-file --batch") + } + + for _, tag := range tags { + commitType, _, ok := next() + if !ok { + return badGit() + } + fileType, fileData, ok := next() + if !ok { + return badGit() + } + f := fileMap[tag] + f.Data = nil + f.Err = nil + switch commitType { + default: + f.Err = fmt.Errorf("unexpected non-commit type %q for rev %s", commitType, tag) + + case "missing": + // Note: f.Err must not satisfy os.IsNotExist. That's reserved for the file not existing in a valid commit. + f.Err = fmt.Errorf("no such rev %s", tag) + missing = append(missing, tag) + + case "tag", "commit": + switch fileType { + default: + f.Err = &os.PathError{Path: tag + ":" + file, Op: "read", Err: fmt.Errorf("unexpected non-blob type %q", fileType)} + case "missing": + f.Err = &os.PathError{Path: tag + ":" + file, Op: "read", Err: os.ErrNotExist} + case "blob": + f.Data = fileData + } + } + } + if len(bytes.TrimSpace(data)) != 0 { + return badGit() + } + + return missing, nil +} + +func (r *gitRepo) RecentTag(rev, prefix string) (tag string, err error) { + info, err := r.Stat(rev) + if err != nil { + return "", err + } + rev = info.Name // expand hash prefixes + + // describe sets tag and err using 'git describe' and reports whether the + // result is definitive. + describe := func() (definitive bool) { + var out []byte + out, err = Run(r.dir, "git", "describe", "--first-parent", "--always", "--abbrev=0", "--match", prefix+"v[0-9]*.[0-9]*.[0-9]*", "--tags", rev) + if err != nil { + return true // Because we use "--always", describe should never fail. + } + + tag = string(bytes.TrimSpace(out)) + return tag != "" && !AllHex(tag) + } + + if describe() { + return tag, err + } + + // Git didn't find a version tag preceding the requested rev. + // See whether any plausible tag exists. + tags, err := r.Tags(prefix + "v") + if err != nil { + return "", err + } + if len(tags) == 0 { + return "", nil + } + + // There are plausible tags, but we don't know if rev is a descendent of any of them. + // Fetch the history to find out. + + r.mu.Lock() + defer r.mu.Unlock() + + if r.fetchLevel < fetchAll { + // Fetch all heads and tags and see if that gives us enough history. + if err := r.fetchUnshallow("refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"); err != nil { + return "", err + } + r.fetchLevel = fetchAll + } + + // If we've reached this point, we have all of the commits that are reachable + // from all heads and tags. + // + // The only refs we should be missing are those that are no longer reachable + // (or never were reachable) from any branch or tag, including the master + // branch, and we don't want to resolve them anyway (they're probably + // unreachable for a reason). + // + // Try one last time in case some other goroutine fetched rev while we were + // waiting on r.mu. + describe() + return tag, err +} + +func (r *gitRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser, actualSubdir string, err error) { + // TODO: Use maxSize or drop it. + args := []string{} + if subdir != "" { + args = append(args, "--", subdir) + } + info, err := r.Stat(rev) // download rev into local git repo + if err != nil { + return nil, "", err + } + + // Incredibly, git produces different archives depending on whether + // it is running on a Windows system or not, in an attempt to normalize + // text file line endings. Setting -c core.autocrlf=input means only + // translate files on the way into the repo, not on the way out (archive). + // The -c core.eol=lf should be unnecessary but set it anyway. + archive, err := Run(r.dir, "git", "-c", "core.autocrlf=input", "-c", "core.eol=lf", "archive", "--format=zip", "--prefix=prefix/", info.Name, args) + if err != nil { + if bytes.Contains(err.(*RunError).Stderr, []byte("did not match any files")) { + return nil, "", os.ErrNotExist + } + return nil, "", err + } + + return ioutil.NopCloser(bytes.NewReader(archive)), "", nil +} diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go b/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go new file mode 100644 index 00000000000..da9e7050407 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/codehost/git_test.go @@ -0,0 +1,635 @@ +// 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 codehost + +import ( + "archive/zip" + "bytes" + "flag" + "fmt" + "internal/testenv" + "io/ioutil" + "log" + "os" + "os/exec" + "path" + "path/filepath" + "reflect" + "strings" + "testing" + "time" +) + +func TestMain(m *testing.M) { + // needed for initializing the test environment variables as testing.Short + // and HasExternalNetwork + flag.Parse() + os.Exit(testMain(m)) +} + +const ( + gitrepo1 = "https://vcs-test.golang.org/git/gitrepo1" + hgrepo1 = "https://vcs-test.golang.org/hg/hgrepo1" +) + +var altRepos = []string{ + "localGitRepo", + hgrepo1, +} + +// TODO: Convert gitrepo1 to svn, bzr, fossil and add tests. +// For now, at least the hgrepo1 tests check the general vcs.go logic. + +// localGitRepo is like gitrepo1 but allows archive access. +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 := ioutil.TempDir("", "gitrepo-test-") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(dir) + WorkRoot = 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) + } + } + + return m.Run() +} + +func testRepo(remote string) (Repo, error) { + if remote == "localGitRepo" { + return LocalGitRepo(filepath.ToSlash(localGitRepo)) + } + kind := "git" + for _, k := range []string{"hg"} { + if strings.Contains(remote, "/"+k+"/") { + kind = k + } + } + return NewRepo(kind, remote) +} + +var tagsTests = []struct { + repo string + prefix string + tags []string +}{ + {gitrepo1, "xxx", []string{}}, + {gitrepo1, "", []string{"v1.2.3", "v1.2.4-annotated", "v2.0.1", "v2.0.2", "v2.3"}}, + {gitrepo1, "v", []string{"v1.2.3", "v1.2.4-annotated", "v2.0.1", "v2.0.2", "v2.3"}}, + {gitrepo1, "v1", []string{"v1.2.3", "v1.2.4-annotated"}}, + {gitrepo1, "2", []string{}}, +} + +func TestTags(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + testenv.MustHaveExec(t) + + for _, tt := range tagsTests { + f := func(t *testing.T) { + r, err := testRepo(tt.repo) + if err != nil { + t.Fatal(err) + } + tags, err := r.Tags(tt.prefix) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(tags, tt.tags) { + t.Errorf("Tags: incorrect tags\nhave %v\nwant %v", tags, tt.tags) + } + } + t.Run(path.Base(tt.repo)+"/"+tt.prefix, f) + if tt.repo == gitrepo1 { + for _, tt.repo = range altRepos { + t.Run(path.Base(tt.repo)+"/"+tt.prefix, f) + } + } + } +} + +var latestTests = []struct { + repo string + info *RevInfo +}{ + { + gitrepo1, + &RevInfo{ + Name: "ede458df7cd0fdca520df19a33158086a8a68e81", + Short: "ede458df7cd0", + Version: "ede458df7cd0fdca520df19a33158086a8a68e81", + Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC), + Tags: []string{"v1.2.3", "v1.2.4-annotated"}, + }, + }, + { + hgrepo1, + &RevInfo{ + Name: "18518c07eb8ed5c80221e997e518cccaa8c0c287", + Short: "18518c07eb8e", + Version: "18518c07eb8ed5c80221e997e518cccaa8c0c287", + Time: time.Date(2018, 6, 27, 16, 16, 30, 0, time.UTC), + }, + }, +} + +func TestLatest(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + testenv.MustHaveExec(t) + + for _, tt := range latestTests { + f := func(t *testing.T) { + r, err := testRepo(tt.repo) + if err != nil { + t.Fatal(err) + } + info, err := r.Latest() + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(info, tt.info) { + t.Errorf("Latest: incorrect info\nhave %+v\nwant %+v", *info, *tt.info) + } + } + t.Run(path.Base(tt.repo), f) + if tt.repo == gitrepo1 { + tt.repo = "localGitRepo" + t.Run(path.Base(tt.repo), f) + } + } +} + +var readFileTests = []struct { + repo string + rev string + file string + err string + data string +}{ + { + repo: gitrepo1, + rev: "latest", + file: "README", + data: "", + }, + { + repo: gitrepo1, + rev: "v2", + file: "another.txt", + data: "another\n", + }, + { + repo: gitrepo1, + rev: "v2.3.4", + file: "another.txt", + err: os.ErrNotExist.Error(), + }, +} + +func TestReadFile(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + testenv.MustHaveExec(t) + + for _, tt := range readFileTests { + f := func(t *testing.T) { + r, err := testRepo(tt.repo) + if err != nil { + t.Fatal(err) + } + data, err := r.ReadFile(tt.rev, tt.file, 100) + if err != nil { + if tt.err == "" { + t.Fatalf("ReadFile: unexpected error %v", err) + } + if !strings.Contains(err.Error(), tt.err) { + t.Fatalf("ReadFile: wrong error %q, want %q", err, tt.err) + } + if len(data) != 0 { + t.Errorf("ReadFile: non-empty data %q with error %v", data, err) + } + return + } + if tt.err != "" { + t.Fatalf("ReadFile: no error, wanted %v", tt.err) + } + if string(data) != tt.data { + t.Errorf("ReadFile: incorrect data\nhave %q\nwant %q", data, tt.data) + } + } + t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.file, f) + if tt.repo == gitrepo1 { + for _, tt.repo = range altRepos { + t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.file, f) + } + } + } +} + +var readZipTests = []struct { + repo string + rev string + subdir string + actualSubdir string + err string + files map[string]uint64 +}{ + { + repo: gitrepo1, + rev: "v2.3.4", + subdir: "", + files: map[string]uint64{ + "prefix/": 0, + "prefix/README": 0, + "prefix/v2": 3, + }, + }, + { + repo: hgrepo1, + rev: "v2.3.4", + subdir: "", + files: map[string]uint64{ + "prefix/.hg_archival.txt": ^uint64(0), + "prefix/README": 0, + "prefix/v2": 3, + }, + }, + + { + repo: gitrepo1, + rev: "v2", + subdir: "", + files: map[string]uint64{ + "prefix/": 0, + "prefix/README": 0, + "prefix/v2": 3, + "prefix/another.txt": 8, + "prefix/foo.txt": 13, + }, + }, + { + repo: hgrepo1, + rev: "v2", + subdir: "", + files: map[string]uint64{ + "prefix/.hg_archival.txt": ^uint64(0), + "prefix/README": 0, + "prefix/v2": 3, + "prefix/another.txt": 8, + "prefix/foo.txt": 13, + }, + }, + + { + repo: gitrepo1, + rev: "v3", + subdir: "", + files: map[string]uint64{ + "prefix/": 0, + "prefix/v3/": 0, + "prefix/v3/sub/": 0, + "prefix/v3/sub/dir/": 0, + "prefix/v3/sub/dir/file.txt": 16, + "prefix/README": 0, + }, + }, + { + repo: hgrepo1, + rev: "v3", + subdir: "", + files: map[string]uint64{ + "prefix/.hg_archival.txt": ^uint64(0), + "prefix/.hgtags": 405, + "prefix/v3/sub/dir/file.txt": 16, + "prefix/README": 0, + }, + }, + + { + repo: gitrepo1, + rev: "v3", + subdir: "v3/sub/dir", + files: map[string]uint64{ + "prefix/": 0, + "prefix/v3/": 0, + "prefix/v3/sub/": 0, + "prefix/v3/sub/dir/": 0, + "prefix/v3/sub/dir/file.txt": 16, + }, + }, + { + repo: hgrepo1, + rev: "v3", + subdir: "v3/sub/dir", + files: map[string]uint64{ + "prefix/v3/sub/dir/file.txt": 16, + }, + }, + + { + repo: gitrepo1, + rev: "v3", + subdir: "v3/sub", + files: map[string]uint64{ + "prefix/": 0, + "prefix/v3/": 0, + "prefix/v3/sub/": 0, + "prefix/v3/sub/dir/": 0, + "prefix/v3/sub/dir/file.txt": 16, + }, + }, + { + repo: hgrepo1, + rev: "v3", + subdir: "v3/sub", + files: map[string]uint64{ + "prefix/v3/sub/dir/file.txt": 16, + }, + }, + + { + repo: gitrepo1, + rev: "aaaaaaaaab", + subdir: "", + err: "unknown revision", + }, + { + repo: hgrepo1, + rev: "aaaaaaaaab", + subdir: "", + err: "unknown revision", + }, + + { + repo: "https://github.com/rsc/vgotest1", + rev: "submod/v1.0.4", + subdir: "submod", + files: map[string]uint64{ + "prefix/": 0, + "prefix/submod/": 0, + "prefix/submod/go.mod": 53, + "prefix/submod/pkg/": 0, + "prefix/submod/pkg/p.go": 31, + }, + }, +} + +type zipFile struct { + name string + size int64 +} + +func TestReadZip(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + testenv.MustHaveExec(t) + + for _, tt := range readZipTests { + f := func(t *testing.T) { + r, err := testRepo(tt.repo) + if err != nil { + t.Fatal(err) + } + rc, actualSubdir, err := r.ReadZip(tt.rev, tt.subdir, 100000) + if err != nil { + if tt.err == "" { + t.Fatalf("ReadZip: unexpected error %v", err) + } + if !strings.Contains(err.Error(), tt.err) { + t.Fatalf("ReadZip: wrong error %q, want %q", err, tt.err) + } + if rc != nil { + t.Errorf("ReadZip: non-nil io.ReadCloser with error %v", err) + } + return + } + defer rc.Close() + if tt.err != "" { + t.Fatalf("ReadZip: no error, wanted %v", tt.err) + } + if actualSubdir != tt.actualSubdir { + t.Fatalf("ReadZip: actualSubdir = %q, want %q", actualSubdir, tt.actualSubdir) + } + zipdata, err := ioutil.ReadAll(rc) + if err != nil { + t.Fatal(err) + } + z, err := zip.NewReader(bytes.NewReader(zipdata), int64(len(zipdata))) + if err != nil { + t.Fatalf("ReadZip: cannot read zip file: %v", err) + } + have := make(map[string]bool) + for _, f := range z.File { + size, ok := tt.files[f.Name] + if !ok { + t.Errorf("ReadZip: unexpected file %s", f.Name) + continue + } + have[f.Name] = true + if size != ^uint64(0) && f.UncompressedSize64 != size { + t.Errorf("ReadZip: file %s has unexpected size %d != %d", f.Name, f.UncompressedSize64, size) + } + } + for name := range tt.files { + if !have[name] { + t.Errorf("ReadZip: missing file %s", name) + } + } + } + t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.subdir, f) + if tt.repo == gitrepo1 { + tt.repo = "localGitRepo" + t.Run(path.Base(tt.repo)+"/"+tt.rev+"/"+tt.subdir, f) + } + } +} + +var hgmap = map[string]string{ + "HEAD": "41964ddce1180313bdc01d0a39a2813344d6261d", // not tip due to bad hgrepo1 conversion + "9d02800338b8a55be062c838d1f02e0c5780b9eb": "8f49ee7a6ddcdec6f0112d9dca48d4a2e4c3c09e", + "76a00fb249b7f93091bc2c89a789dab1fc1bc26f": "88fde824ec8b41a76baa16b7e84212cee9f3edd0", + "ede458df7cd0fdca520df19a33158086a8a68e81": "41964ddce1180313bdc01d0a39a2813344d6261d", + "97f6aa59c81c623494825b43d39e445566e429a4": "c0cbbfb24c7c3c50c35c7b88e7db777da4ff625d", +} + +var statTests = []struct { + repo string + rev string + err string + info *RevInfo +}{ + { + repo: gitrepo1, + rev: "HEAD", + info: &RevInfo{ + Name: "ede458df7cd0fdca520df19a33158086a8a68e81", + Short: "ede458df7cd0", + Version: "ede458df7cd0fdca520df19a33158086a8a68e81", + Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC), + Tags: []string{"v1.2.3", "v1.2.4-annotated"}, + }, + }, + { + repo: gitrepo1, + rev: "v2", // branch + info: &RevInfo{ + Name: "9d02800338b8a55be062c838d1f02e0c5780b9eb", + Short: "9d02800338b8", + Version: "9d02800338b8a55be062c838d1f02e0c5780b9eb", + Time: time.Date(2018, 4, 17, 20, 00, 32, 0, time.UTC), + Tags: []string{"v2.0.2"}, + }, + }, + { + repo: gitrepo1, + rev: "v2.3.4", // badly-named branch (semver should be a tag) + info: &RevInfo{ + Name: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f", + Short: "76a00fb249b7", + Version: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f", + Time: time.Date(2018, 4, 17, 19, 45, 48, 0, time.UTC), + Tags: []string{"v2.0.1", "v2.3"}, + }, + }, + { + repo: gitrepo1, + rev: "v2.3", // badly-named tag (we only respect full semver v2.3.0) + info: &RevInfo{ + Name: "76a00fb249b7f93091bc2c89a789dab1fc1bc26f", + Short: "76a00fb249b7", + Version: "v2.3", + Time: time.Date(2018, 4, 17, 19, 45, 48, 0, time.UTC), + Tags: []string{"v2.0.1", "v2.3"}, + }, + }, + { + repo: gitrepo1, + rev: "v1.2.3", // tag + info: &RevInfo{ + Name: "ede458df7cd0fdca520df19a33158086a8a68e81", + Short: "ede458df7cd0", + Version: "v1.2.3", + Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC), + Tags: []string{"v1.2.3", "v1.2.4-annotated"}, + }, + }, + { + repo: gitrepo1, + rev: "ede458df", // hash prefix in refs + info: &RevInfo{ + Name: "ede458df7cd0fdca520df19a33158086a8a68e81", + Short: "ede458df7cd0", + Version: "ede458df7cd0fdca520df19a33158086a8a68e81", + Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC), + Tags: []string{"v1.2.3", "v1.2.4-annotated"}, + }, + }, + { + repo: gitrepo1, + rev: "97f6aa59", // hash prefix not in refs + info: &RevInfo{ + Name: "97f6aa59c81c623494825b43d39e445566e429a4", + Short: "97f6aa59c81c", + Version: "97f6aa59c81c623494825b43d39e445566e429a4", + Time: time.Date(2018, 4, 17, 20, 0, 19, 0, time.UTC), + }, + }, + { + repo: gitrepo1, + rev: "v1.2.4-annotated", // annotated tag uses unwrapped commit hash + info: &RevInfo{ + Name: "ede458df7cd0fdca520df19a33158086a8a68e81", + Short: "ede458df7cd0", + Version: "v1.2.4-annotated", + Time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC), + Tags: []string{"v1.2.3", "v1.2.4-annotated"}, + }, + }, + { + repo: gitrepo1, + rev: "aaaaaaaaab", + err: "unknown revision", + }, +} + +func TestStat(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + testenv.MustHaveExec(t) + + for _, tt := range statTests { + f := func(t *testing.T) { + r, err := testRepo(tt.repo) + if err != nil { + t.Fatal(err) + } + info, err := r.Stat(tt.rev) + if err != nil { + if tt.err == "" { + t.Fatalf("Stat: unexpected error %v", err) + } + if !strings.Contains(err.Error(), tt.err) { + t.Fatalf("Stat: wrong error %q, want %q", err, tt.err) + } + if info != nil { + t.Errorf("Stat: non-nil info with error %q", err) + } + return + } + if !reflect.DeepEqual(info, tt.info) { + t.Errorf("Stat: incorrect info\nhave %+v\nwant %+v", *info, *tt.info) + } + } + t.Run(path.Base(tt.repo)+"/"+tt.rev, f) + if tt.repo == gitrepo1 { + for _, tt.repo = range altRepos { + old := tt + var m map[string]string + if tt.repo == hgrepo1 { + m = hgmap + } + if tt.info != nil { + info := *tt.info + tt.info = &info + tt.info.Name = remap(tt.info.Name, m) + tt.info.Version = remap(tt.info.Version, m) + tt.info.Short = remap(tt.info.Short, m) + } + tt.rev = remap(tt.rev, m) + t.Run(path.Base(tt.repo)+"/"+tt.rev, f) + tt = old + } + } + } +} + +func remap(name string, m map[string]string) string { + if m[name] != "" { + return m[name] + } + if AllHex(name) { + for k, v := range m { + if strings.HasPrefix(k, name) { + return v[:len(name)] + } + } + } + return name +} diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/shell.go b/libgo/go/cmd/go/internal/modfetch/codehost/shell.go new file mode 100644 index 00000000000..7b813c37401 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/codehost/shell.go @@ -0,0 +1,140 @@ +// 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 + +// Interactive debugging shell for codehost.Repo implementations. + +package main + +import ( + "archive/zip" + "bufio" + "bytes" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "strings" + "time" + + "cmd/go/internal/modfetch/codehost" +) + +func usage() { + fmt.Fprintf(os.Stderr, "usage: go run shell.go vcs remote\n") + os.Exit(2) +} + +func main() { + codehost.WorkRoot = "/tmp/vcswork" + log.SetFlags(0) + log.SetPrefix("shell: ") + flag.Usage = usage + flag.Parse() + if flag.NArg() != 2 { + usage() + } + + repo, err := codehost.NewRepo(flag.Arg(0), flag.Arg(1)) + if err != nil { + log.Fatal(err) + } + + b := bufio.NewReader(os.Stdin) + for { + fmt.Fprintf(os.Stderr, ">>> ") + line, err := b.ReadString('\n') + if err != nil { + log.Fatal(err) + } + f := strings.Fields(line) + if len(f) == 0 { + continue + } + switch f[0] { + default: + fmt.Fprintf(os.Stderr, "?unknown command\n") + continue + case "tags": + prefix := "" + if len(f) == 2 { + prefix = f[1] + } + if len(f) > 2 { + fmt.Fprintf(os.Stderr, "?usage: tags [prefix]\n") + continue + } + tags, err := repo.Tags(prefix) + if err != nil { + fmt.Fprintf(os.Stderr, "?%s\n", err) + continue + } + for _, tag := range tags { + fmt.Printf("%s\n", tag) + } + + case "stat": + if len(f) != 2 { + fmt.Fprintf(os.Stderr, "?usage: stat rev\n") + continue + } + info, err := repo.Stat(f[1]) + if err != nil { + fmt.Fprintf(os.Stderr, "?%s\n", err) + continue + } + fmt.Printf("name=%s short=%s version=%s time=%s\n", info.Name, info.Short, info.Version, info.Time.UTC().Format(time.RFC3339)) + + case "read": + if len(f) != 3 { + fmt.Fprintf(os.Stderr, "?usage: read rev file\n") + continue + } + data, err := repo.ReadFile(f[1], f[2], 10<<20) + if err != nil { + fmt.Fprintf(os.Stderr, "?%s\n", err) + continue + } + os.Stdout.Write(data) + + case "zip": + if len(f) != 4 { + fmt.Fprintf(os.Stderr, "?usage: zip rev subdir output\n") + continue + } + subdir := f[2] + if subdir == "-" { + subdir = "" + } + rc, _, err := repo.ReadZip(f[1], subdir, 10<<20) + if err != nil { + fmt.Fprintf(os.Stderr, "?%s\n", err) + continue + } + data, err := ioutil.ReadAll(rc) + rc.Close() + if err != nil { + fmt.Fprintf(os.Stderr, "?%s\n", err) + continue + } + + if f[3] != "-" { + if err := ioutil.WriteFile(f[3], data, 0666); err != nil { + fmt.Fprintf(os.Stderr, "?%s\n", err) + continue + } + } + z, err := zip.NewReader(bytes.NewReader(data), int64(len(data))) + if err != nil { + fmt.Fprintf(os.Stderr, "?%s\n", err) + continue + } + for _, f := range z.File { + fmt.Printf("%s %d\n", f.Name, f.UncompressedSize64) + } + } + } +} diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/vcs.go b/libgo/go/cmd/go/internal/modfetch/codehost/vcs.go new file mode 100644 index 00000000000..9e862a0ef8c --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/codehost/vcs.go @@ -0,0 +1,528 @@ +// 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 codehost + +import ( + "encoding/xml" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "regexp" + "sort" + "strconv" + "strings" + "sync" + "time" + + "cmd/go/internal/par" + "cmd/go/internal/str" +) + +// A VCSError indicates an error using a version control system. +// The implication of a VCSError is that we know definitively where +// to get the code, but we can't access it due to the error. +// The caller should report this error instead of continuing to probe +// other possible module paths. +type VCSError struct { + Err error +} + +func (e *VCSError) Error() string { return e.Err.Error() } + +func NewRepo(vcs, remote string) (Repo, error) { + type key struct { + vcs string + remote string + } + type cached struct { + repo Repo + err error + } + c := vcsRepoCache.Do(key{vcs, remote}, func() interface{} { + repo, err := newVCSRepo(vcs, remote) + if err != nil { + err = &VCSError{err} + } + return cached{repo, err} + }).(cached) + + return c.repo, c.err +} + +var vcsRepoCache par.Cache + +type vcsRepo struct { + remote string + cmd *vcsCmd + dir string + + tagsOnce sync.Once + tags map[string]bool + + branchesOnce sync.Once + branches map[string]bool + + fetchOnce sync.Once + fetchErr error +} + +func newVCSRepo(vcs, remote string) (Repo, error) { + if vcs == "git" { + return newGitRepo(remote, false) + } + cmd := vcsCmds[vcs] + if cmd == nil { + return nil, fmt.Errorf("unknown vcs: %s %s", vcs, remote) + } + if !strings.Contains(remote, "://") { + return nil, fmt.Errorf("invalid vcs remote: %s %s", vcs, remote) + } + r := &vcsRepo{remote: remote, cmd: cmd} + if cmd.init == nil { + return r, nil + } + dir, err := WorkDir(vcsWorkDirType+vcs, r.remote) + if err != nil { + return nil, err + } + r.dir = dir + if _, err := os.Stat(filepath.Join(dir, "."+vcs)); err != nil { + if _, err := Run(dir, cmd.init(r.remote)); err != nil { + os.RemoveAll(dir) + return nil, err + } + } + return r, nil +} + +const vcsWorkDirType = "vcs1." + +type vcsCmd struct { + vcs string // vcs name "hg" + init func(remote string) []string // cmd to init repo to track remote + tags func(remote string) []string // cmd to list local tags + tagRE *regexp.Regexp // regexp to extract tag names from output of tags cmd + branches func(remote string) []string // cmd to list local branches + branchRE *regexp.Regexp // regexp to extract branch names from output of tags cmd + badLocalRevRE *regexp.Regexp // regexp of names that must not be served out of local cache without doing fetch first + statLocal func(rev, remote string) []string // cmd to stat local rev + parseStat func(rev, out string) (*RevInfo, error) // cmd to parse output of statLocal + fetch []string // cmd to fetch everything from remote + latest string // name of latest commit on remote (tip, HEAD, etc) + readFile func(rev, file, remote string) []string // cmd to read rev's file + readZip func(rev, subdir, remote, target string) []string // cmd to read rev's subdir as zip file +} + +var re = regexp.MustCompile + +var vcsCmds = map[string]*vcsCmd{ + "hg": { + vcs: "hg", + init: func(remote string) []string { + return []string{"hg", "clone", "-U", remote, "."} + }, + tags: func(remote string) []string { + return []string{"hg", "tags", "-q"} + }, + tagRE: re(`(?m)^[^\n]+$`), + branches: func(remote string) []string { + return []string{"hg", "branches", "-c", "-q"} + }, + branchRE: re(`(?m)^[^\n]+$`), + badLocalRevRE: re(`(?m)^(tip)$`), + statLocal: func(rev, remote string) []string { + return []string{"hg", "log", "-l1", "-r", rev, "--template", "{node} {date|hgdate} {tags}"} + }, + parseStat: hgParseStat, + fetch: []string{"hg", "pull", "-f"}, + latest: "tip", + readFile: func(rev, file, remote string) []string { + return []string{"hg", "cat", "-r", rev, file} + }, + readZip: func(rev, subdir, remote, target string) []string { + pattern := []string{} + if subdir != "" { + pattern = []string{"-I", subdir + "/**"} + } + return str.StringList("hg", "archive", "-t", "zip", "--no-decode", "-r", rev, "--prefix=prefix/", pattern, target) + }, + }, + + "svn": { + vcs: "svn", + init: nil, // no local checkout + tags: func(remote string) []string { + return []string{"svn", "list", strings.TrimSuffix(remote, "/trunk") + "/tags"} + }, + tagRE: re(`(?m)^(.*?)/?$`), + statLocal: func(rev, remote string) []string { + suffix := "@" + rev + if rev == "latest" { + suffix = "" + } + return []string{"svn", "log", "-l1", "--xml", remote + suffix} + }, + parseStat: svnParseStat, + latest: "latest", + readFile: func(rev, file, remote string) []string { + return []string{"svn", "cat", remote + "/" + file + "@" + rev} + }, + // TODO: zip + }, + + "bzr": { + vcs: "bzr", + init: func(remote string) []string { + return []string{"bzr", "branch", "--use-existing-dir", remote, "."} + }, + fetch: []string{ + "bzr", "pull", "--overwrite-tags", + }, + tags: func(remote string) []string { + return []string{"bzr", "tags"} + }, + tagRE: re(`(?m)^\S+`), + badLocalRevRE: re(`^revno:-`), + statLocal: func(rev, remote string) []string { + return []string{"bzr", "log", "-l1", "--long", "--show-ids", "-r", rev} + }, + parseStat: bzrParseStat, + latest: "revno:-1", + readFile: func(rev, file, remote string) []string { + return []string{"bzr", "cat", "-r", rev, file} + }, + readZip: func(rev, subdir, remote, target string) []string { + extra := []string{} + if subdir != "" { + extra = []string{"./" + subdir} + } + return str.StringList("bzr", "export", "--format=zip", "-r", rev, "--root=prefix/", target, extra) + }, + }, + + "fossil": { + vcs: "fossil", + init: func(remote string) []string { + return []string{"fossil", "clone", remote, ".fossil"} + }, + fetch: []string{"fossil", "pull", "-R", ".fossil"}, + tags: func(remote string) []string { + return []string{"fossil", "tag", "-R", ".fossil", "list"} + }, + tagRE: re(`XXXTODO`), + statLocal: func(rev, remote string) []string { + return []string{"fossil", "info", "-R", ".fossil", rev} + }, + parseStat: fossilParseStat, + latest: "trunk", + readFile: func(rev, file, remote string) []string { + return []string{"fossil", "cat", "-R", ".fossil", "-r", rev, file} + }, + readZip: func(rev, subdir, remote, target string) []string { + extra := []string{} + if subdir != "" && !strings.ContainsAny(subdir, "*?[],") { + extra = []string{"--include", subdir} + } + // Note that vcsRepo.ReadZip below rewrites this command + // to run in a different directory, to work around a fossil bug. + return str.StringList("fossil", "zip", "-R", ".fossil", "--name", "prefix", extra, rev, target) + }, + }, +} + +func (r *vcsRepo) loadTags() { + out, err := Run(r.dir, r.cmd.tags(r.remote)) + if err != nil { + return + } + + // Run tag-listing command and extract tags. + r.tags = make(map[string]bool) + for _, tag := range r.cmd.tagRE.FindAllString(string(out), -1) { + if r.cmd.badLocalRevRE != nil && r.cmd.badLocalRevRE.MatchString(tag) { + continue + } + r.tags[tag] = true + } +} + +func (r *vcsRepo) loadBranches() { + if r.cmd.branches == nil { + return + } + + out, err := Run(r.dir, r.cmd.branches(r.remote)) + if err != nil { + return + } + + r.branches = make(map[string]bool) + for _, branch := range r.cmd.branchRE.FindAllString(string(out), -1) { + if r.cmd.badLocalRevRE != nil && r.cmd.badLocalRevRE.MatchString(branch) { + continue + } + r.branches[branch] = true + } +} + +func (r *vcsRepo) Tags(prefix string) ([]string, error) { + r.tagsOnce.Do(r.loadTags) + + tags := []string{} + for tag := range r.tags { + if strings.HasPrefix(tag, prefix) { + tags = append(tags, tag) + } + } + sort.Strings(tags) + return tags, nil +} + +func (r *vcsRepo) Stat(rev string) (*RevInfo, error) { + if rev == "latest" { + rev = r.cmd.latest + } + r.branchesOnce.Do(r.loadBranches) + revOK := (r.cmd.badLocalRevRE == nil || !r.cmd.badLocalRevRE.MatchString(rev)) && !r.branches[rev] + if revOK { + if info, err := r.statLocal(rev); err == nil { + return info, nil + } + } + + r.fetchOnce.Do(r.fetch) + if r.fetchErr != nil { + return nil, r.fetchErr + } + info, err := r.statLocal(rev) + if err != nil { + return nil, err + } + if !revOK { + info.Version = info.Name + } + return info, nil +} + +func (r *vcsRepo) fetch() { + _, r.fetchErr = Run(r.dir, r.cmd.fetch) +} + +func (r *vcsRepo) statLocal(rev string) (*RevInfo, error) { + out, err := Run(r.dir, r.cmd.statLocal(rev, r.remote)) + if err != nil { + return nil, fmt.Errorf("unknown revision %s", rev) + } + return r.cmd.parseStat(rev, string(out)) +} + +func (r *vcsRepo) Latest() (*RevInfo, error) { + return r.Stat("latest") +} + +func (r *vcsRepo) ReadFile(rev, file string, maxSize int64) ([]byte, error) { + if rev == "latest" { + rev = r.cmd.latest + } + _, err := r.Stat(rev) // download rev into local repo + if err != nil { + return nil, err + } + out, err := Run(r.dir, r.cmd.readFile(rev, file, r.remote)) + if err != nil { + return nil, os.ErrNotExist + } + return out, nil +} + +func (r *vcsRepo) ReadFileRevs(revs []string, file string, maxSize int64) (map[string]*FileRev, error) { + return nil, fmt.Errorf("ReadFileRevs not implemented") +} + +func (r *vcsRepo) RecentTag(rev, prefix string) (tag string, err error) { + return "", fmt.Errorf("RecentTags not implemented") +} + +func (r *vcsRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser, actualSubdir string, err error) { + if rev == "latest" { + rev = r.cmd.latest + } + f, err := ioutil.TempFile("", "go-readzip-*.zip") + if err != nil { + return nil, "", err + } + if r.cmd.vcs == "fossil" { + // If you run + // fossil zip -R .fossil --name prefix trunk /tmp/x.zip + // fossil fails with "unable to create directory /tmp" [sic]. + // Change the command to run in /tmp instead, + // replacing the -R argument with an absolute path. + args := r.cmd.readZip(rev, subdir, r.remote, filepath.Base(f.Name())) + for i := range args { + if args[i] == ".fossil" { + args[i] = filepath.Join(r.dir, ".fossil") + } + } + _, err = Run(filepath.Dir(f.Name()), args) + } else { + _, err = Run(r.dir, r.cmd.readZip(rev, subdir, r.remote, f.Name())) + } + if err != nil { + f.Close() + os.Remove(f.Name()) + return nil, "", err + } + return &deleteCloser{f}, "", nil +} + +// deleteCloser is a file that gets deleted on Close. +type deleteCloser struct { + *os.File +} + +func (d *deleteCloser) Close() error { + defer os.Remove(d.File.Name()) + return d.File.Close() +} + +func hgParseStat(rev, out string) (*RevInfo, error) { + f := strings.Fields(string(out)) + if len(f) < 3 { + return nil, fmt.Errorf("unexpected response from hg log: %q", out) + } + hash := f[0] + version := rev + if strings.HasPrefix(hash, version) { + version = hash // extend to full hash + } + t, err := strconv.ParseInt(f[1], 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid time from hg log: %q", out) + } + + var tags []string + for _, tag := range f[3:] { + if tag != "tip" { + tags = append(tags, tag) + } + } + sort.Strings(tags) + + info := &RevInfo{ + Name: hash, + Short: ShortenSHA1(hash), + Time: time.Unix(t, 0).UTC(), + Version: version, + Tags: tags, + } + return info, nil +} + +func svnParseStat(rev, out string) (*RevInfo, error) { + var log struct { + Logentry struct { + Revision int64 `xml:"revision,attr"` + Date string `xml:"date"` + } `xml:"logentry"` + } + if err := xml.Unmarshal([]byte(out), &log); err != nil { + return nil, fmt.Errorf("unexpected response from svn log --xml: %v\n%s", err, out) + } + + t, err := time.Parse(time.RFC3339, log.Logentry.Date) + if err != nil { + return nil, fmt.Errorf("unexpected response from svn log --xml: %v\n%s", err, out) + } + + info := &RevInfo{ + Name: fmt.Sprintf("%d", log.Logentry.Revision), + Short: fmt.Sprintf("%012d", log.Logentry.Revision), + Time: t.UTC(), + Version: rev, + } + return info, nil +} + +func bzrParseStat(rev, out string) (*RevInfo, error) { + var revno int64 + var tm time.Time + for _, line := range strings.Split(out, "\n") { + if line == "" || line[0] == ' ' || line[0] == '\t' { + // End of header, start of commit message. + break + } + if line[0] == '-' { + continue + } + i := strings.Index(line, ":") + if i < 0 { + // End of header, start of commit message. + break + } + key, val := line[:i], strings.TrimSpace(line[i+1:]) + switch key { + case "revno": + if j := strings.Index(val, " "); j >= 0 { + val = val[:j] + } + i, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return nil, fmt.Errorf("unexpected revno from bzr log: %q", line) + } + revno = i + case "timestamp": + j := strings.Index(val, " ") + if j < 0 { + return nil, fmt.Errorf("unexpected timestamp from bzr log: %q", line) + } + t, err := time.Parse("2006-01-02 15:04:05 -0700", val[j+1:]) + if err != nil { + return nil, fmt.Errorf("unexpected timestamp from bzr log: %q", line) + } + tm = t.UTC() + } + } + if revno == 0 || tm.IsZero() { + return nil, fmt.Errorf("unexpected response from bzr log: %q", out) + } + + info := &RevInfo{ + Name: fmt.Sprintf("%d", revno), + Short: fmt.Sprintf("%012d", revno), + Time: tm, + Version: rev, + } + return info, nil +} + +func fossilParseStat(rev, out string) (*RevInfo, error) { + for _, line := range strings.Split(out, "\n") { + if strings.HasPrefix(line, "uuid:") { + f := strings.Fields(line) + if len(f) != 5 || len(f[1]) != 40 || f[4] != "UTC" { + return nil, fmt.Errorf("unexpected response from fossil info: %q", line) + } + t, err := time.Parse("2006-01-02 15:04:05", f[2]+" "+f[3]) + if err != nil { + return nil, fmt.Errorf("unexpected response from fossil info: %q", line) + } + hash := f[1] + version := rev + if strings.HasPrefix(hash, version) { + version = hash // extend to full hash + } + info := &RevInfo{ + Name: hash, + Short: ShortenSHA1(hash), + Time: t, + Version: version, + } + return info, nil + } + } + return nil, fmt.Errorf("unexpected response from fossil info: %q", out) +} diff --git a/libgo/go/cmd/go/internal/modfetch/coderepo.go b/libgo/go/cmd/go/internal/modfetch/coderepo.go new file mode 100644 index 00000000000..9cf0e911508 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/coderepo.go @@ -0,0 +1,605 @@ +// 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 ( + "archive/zip" + "fmt" + "io" + "io/ioutil" + "os" + "path" + "strings" + + "cmd/go/internal/modfetch/codehost" + "cmd/go/internal/modfile" + "cmd/go/internal/module" + "cmd/go/internal/semver" +) + +// A codeRepo implements modfetch.Repo using an underlying codehost.Repo. +type codeRepo struct { + modPath string + + code codehost.Repo + codeRoot string + codeDir string + + path string + pathPrefix string + pathMajor string + pseudoMajor string +} + +func newCodeRepo(code codehost.Repo, root, path string) (Repo, error) { + if !hasPathPrefix(path, root) { + return nil, fmt.Errorf("mismatched repo: found %s for %s", root, path) + } + pathPrefix, pathMajor, ok := module.SplitPathVersion(path) + if !ok { + return nil, fmt.Errorf("invalid module path %q", path) + } + pseudoMajor := "v0" + if pathMajor != "" { + pseudoMajor = pathMajor[1:] + } + + // At this point we might have: + // codeRoot = github.com/rsc/foo + // path = github.com/rsc/foo/bar/v2 + // pathPrefix = github.com/rsc/foo/bar + // pathMajor = /v2 + // pseudoMajor = v2 + // + // Compute codeDir = bar, the subdirectory within the repo + // corresponding to the module root. + codeDir := strings.Trim(strings.TrimPrefix(pathPrefix, root), "/") + if strings.HasPrefix(path, "gopkg.in/") { + // But gopkg.in is a special legacy case, in which pathPrefix does not start with codeRoot. + // For example we might have: + // codeRoot = gopkg.in/yaml.v2 + // pathPrefix = gopkg.in/yaml + // pathMajor = .v2 + // pseudoMajor = v2 + // codeDir = pathPrefix (because codeRoot is not a prefix of pathPrefix) + // Clear codeDir - the module root is the repo root for gopkg.in repos. + codeDir = "" + } + + r := &codeRepo{ + modPath: path, + code: code, + codeRoot: root, + codeDir: codeDir, + pathPrefix: pathPrefix, + pathMajor: pathMajor, + pseudoMajor: pseudoMajor, + } + + return r, nil +} + +func (r *codeRepo) ModulePath() string { + return r.modPath +} + +func (r *codeRepo) Versions(prefix string) ([]string, error) { + // Special case: gopkg.in/macaroon-bakery.v2-unstable + // does not use the v2 tags (those are for macaroon-bakery.v2). + // It has no possible tags at all. + if strings.HasPrefix(r.modPath, "gopkg.in/") && strings.HasSuffix(r.modPath, "-unstable") { + return nil, nil + } + + p := prefix + if r.codeDir != "" { + p = r.codeDir + "/" + p + } + tags, err := r.code.Tags(p) + if err != nil { + return nil, err + } + + list := []string{} + var incompatible []string + for _, tag := range tags { + if !strings.HasPrefix(tag, p) { + continue + } + v := tag + if r.codeDir != "" { + v = v[len(r.codeDir)+1:] + } + if v == "" || v != module.CanonicalVersion(v) || IsPseudoVersion(v) { + continue + } + if !module.MatchPathMajor(v, r.pathMajor) { + if r.codeDir == "" && r.pathMajor == "" && semver.Major(v) > "v1" { + incompatible = append(incompatible, v) + } + continue + } + list = append(list, v) + } + + if len(incompatible) > 0 { + // Check for later versions that were created not following semantic import versioning, + // as indicated by the absence of a go.mod file. Those versions can be addressed + // by referring to them with a +incompatible suffix, as in v17.0.0+incompatible. + files, err := r.code.ReadFileRevs(incompatible, "go.mod", codehost.MaxGoMod) + if err != nil { + return nil, err + } + for _, rev := range incompatible { + f := files[rev] + if os.IsNotExist(f.Err) { + list = append(list, rev+"+incompatible") + } + } + } + + SortVersions(list) + return list, nil +} + +func (r *codeRepo) Stat(rev string) (*RevInfo, error) { + if rev == "latest" { + return r.Latest() + } + codeRev := r.revToRev(rev) + if semver.IsValid(codeRev) && r.codeDir != "" { + codeRev = r.codeDir + "/" + codeRev + } + info, err := r.code.Stat(codeRev) + if err != nil { + return nil, err + } + return r.convert(info, rev) +} + +func (r *codeRepo) Latest() (*RevInfo, error) { + info, err := r.code.Latest() + if err != nil { + return nil, err + } + return r.convert(info, "") +} + +func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, error) { + info2 := &RevInfo{ + Name: info.Name, + Short: info.Short, + Time: info.Time, + } + + // Determine version. + if module.CanonicalVersion(statVers) == statVers && module.MatchPathMajor(statVers, r.pathMajor) { + // The original call was repo.Stat(statVers), and requestedVersion is OK, so use it. + info2.Version = statVers + } else { + // Otherwise derive a version from a code repo tag. + // Tag must have a prefix matching codeDir. + p := "" + if r.codeDir != "" { + p = r.codeDir + "/" + } + + // If this is a plain tag (no dir/ prefix) + // and the module path is unversioned, + // and if the underlying file tree has no go.mod, + // then allow using the tag with a +incompatible suffix. + canUseIncompatible := false + if r.codeDir == "" && r.pathMajor == "" { + _, errGoMod := r.code.ReadFile(info.Name, "go.mod", codehost.MaxGoMod) + if errGoMod != nil { + canUseIncompatible = true + } + } + + tagToVersion := func(v string) string { + if !strings.HasPrefix(v, p) { + return "" + } + v = v[len(p):] + if module.CanonicalVersion(v) != v || IsPseudoVersion(v) { + return "" + } + if module.MatchPathMajor(v, r.pathMajor) { + return v + } + if canUseIncompatible { + return v + "+incompatible" + } + return "" + } + + // If info.Version is OK, use it. + if v := tagToVersion(info.Version); v != "" { + info2.Version = v + } else { + // Otherwise look through all known tags for latest in semver ordering. + for _, tag := range info.Tags { + if v := tagToVersion(tag); v != "" && semver.Compare(info2.Version, v) < 0 { + info2.Version = v + } + } + // Otherwise make a pseudo-version. + if info2.Version == "" { + tag, _ := r.code.RecentTag(statVers, p) + v = tagToVersion(tag) + // TODO: Check that v is OK for r.pseudoMajor or else is OK for incompatible. + info2.Version = PseudoVersion(r.pseudoMajor, v, info.Time, info.Short) + } + } + } + + // Do not allow a successful stat of a pseudo-version for a subdirectory + // unless the subdirectory actually does have a go.mod. + if IsPseudoVersion(info2.Version) && r.codeDir != "" { + _, _, _, err := r.findDir(info2.Version) + if err != nil { + // TODO: It would be nice to return an error like "not a module". + // Right now we return "missing go.mod", which is a little confusing. + return nil, err + } + } + + return info2, nil +} + +func (r *codeRepo) revToRev(rev string) string { + if semver.IsValid(rev) { + if IsPseudoVersion(rev) { + r, _ := PseudoVersionRev(rev) + return r + } + if semver.Build(rev) == "+incompatible" { + rev = rev[:len(rev)-len("+incompatible")] + } + if r.codeDir == "" { + return rev + } + return r.codeDir + "/" + rev + } + return rev +} + +func (r *codeRepo) versionToRev(version string) (rev string, err error) { + if !semver.IsValid(version) { + return "", fmt.Errorf("malformed semantic version %q", version) + } + return r.revToRev(version), nil +} + +func (r *codeRepo) findDir(version string) (rev, dir string, gomod []byte, err error) { + rev, err = r.versionToRev(version) + if err != nil { + return "", "", nil, err + } + + // Load info about go.mod but delay consideration + // (except I/O error) until we rule out v2/go.mod. + file1 := path.Join(r.codeDir, "go.mod") + gomod1, err1 := r.code.ReadFile(rev, file1, codehost.MaxGoMod) + if err1 != nil && !os.IsNotExist(err1) { + return "", "", nil, fmt.Errorf("reading %s/%s at revision %s: %v", r.pathPrefix, file1, rev, err1) + } + mpath1 := modfile.ModulePath(gomod1) + found1 := err1 == nil && isMajor(mpath1, r.pathMajor) + + var file2 string + if r.pathMajor != "" && !strings.HasPrefix(r.pathMajor, ".") { + // Suppose pathMajor is "/v2". + // Either go.mod should claim v2 and v2/go.mod should not exist, + // or v2/go.mod should exist and claim v2. Not both. + // Note that we don't check the full path, just the major suffix, + // because of replacement modules. This might be a fork of + // the real module, found at a different path, usable only in + // a replace directive. + dir2 := path.Join(r.codeDir, r.pathMajor[1:]) + file2 = path.Join(dir2, "go.mod") + gomod2, err2 := r.code.ReadFile(rev, file2, codehost.MaxGoMod) + if err2 != nil && !os.IsNotExist(err2) { + return "", "", nil, fmt.Errorf("reading %s/%s at revision %s: %v", r.pathPrefix, file2, rev, err2) + } + mpath2 := modfile.ModulePath(gomod2) + found2 := err2 == nil && isMajor(mpath2, r.pathMajor) + + if found1 && found2 { + return "", "", nil, fmt.Errorf("%s/%s and ...%s/go.mod both have ...%s module paths at revision %s", r.pathPrefix, file1, r.pathMajor, r.pathMajor, rev) + } + if found2 { + return rev, dir2, gomod2, nil + } + if err2 == nil { + if mpath2 == "" { + return "", "", nil, fmt.Errorf("%s/%s is missing module path at revision %s", r.pathPrefix, file2, rev) + } + return "", "", nil, fmt.Errorf("%s/%s has non-...%s module path %q at revision %s", r.pathPrefix, file2, r.pathMajor, mpath2, rev) + } + } + + // Not v2/go.mod, so it's either go.mod or nothing. Which is it? + if found1 { + // Explicit go.mod with matching module path OK. + return rev, r.codeDir, gomod1, nil + } + if err1 == nil { + // Explicit go.mod with non-matching module path disallowed. + suffix := "" + if file2 != "" { + suffix = fmt.Sprintf(" (and ...%s/go.mod does not exist)", r.pathMajor) + } + if mpath1 == "" { + return "", "", nil, fmt.Errorf("%s is missing module path%s at revision %s", file1, suffix, rev) + } + if r.pathMajor != "" { // ".v1", ".v2" for gopkg.in + return "", "", nil, fmt.Errorf("%s has non-...%s module path %q%s at revision %s", file1, r.pathMajor, mpath1, suffix, rev) + } + return "", "", nil, fmt.Errorf("%s has post-%s module path %q%s at revision %s", file1, semver.Major(version), mpath1, suffix, rev) + } + + if r.codeDir == "" && (r.pathMajor == "" || strings.HasPrefix(r.pathMajor, ".")) { + // Implicit go.mod at root of repo OK for v0/v1 and for gopkg.in. + return rev, "", nil, nil + } + + // Implicit go.mod below root of repo or at v2+ disallowed. + // Be clear about possibility of using either location for v2+. + if file2 != "" { + return "", "", nil, fmt.Errorf("missing %s/go.mod and ...%s/go.mod at revision %s", r.pathPrefix, r.pathMajor, rev) + } + return "", "", nil, fmt.Errorf("missing %s/go.mod at revision %s", r.pathPrefix, rev) +} + +func isMajor(mpath, pathMajor string) bool { + if mpath == "" { + return false + } + if pathMajor == "" { + // mpath must NOT have version suffix. + i := len(mpath) + for i > 0 && '0' <= mpath[i-1] && mpath[i-1] <= '9' { + i-- + } + if i < len(mpath) && i >= 2 && mpath[i-1] == 'v' && mpath[i-2] == '/' { + // Found valid suffix. + return false + } + return true + } + // Otherwise pathMajor is ".v1", ".v2" (gopkg.in), or "/v2", "/v3" etc. + return strings.HasSuffix(mpath, pathMajor) +} + +func (r *codeRepo) GoMod(version string) (data []byte, err error) { + rev, dir, gomod, err := r.findDir(version) + if err != nil { + return nil, err + } + if gomod != nil { + return gomod, nil + } + 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 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))) +} + +func (r *codeRepo) modPrefix(rev string) string { + return r.modPath + "@" + rev +} + +func (r *codeRepo) Zip(version string, tmpdir string) (tmpfile string, err error) { + rev, dir, _, err := r.findDir(version) + if err != nil { + return "", err + } + dl, actualDir, err := r.code.ReadZip(rev, dir, codehost.MaxZipFile) + if err != nil { + return "", err + } + if actualDir != "" && !hasPathPrefix(dir, actualDir) { + return "", fmt.Errorf("internal error: downloading %v %v: dir=%q but actualDir=%q", r.path, rev, dir, actualDir) + } + subdir := strings.Trim(strings.TrimPrefix(dir, actualDir), "/") + + // Spool to local file. + f, err := ioutil.TempFile(tmpdir, "go-codehost-") + if err != nil { + dl.Close() + return "", err + } + defer os.Remove(f.Name()) + defer f.Close() + maxSize := int64(codehost.MaxZipFile) + lr := &io.LimitedReader{R: dl, N: maxSize + 1} + if _, err := io.Copy(f, lr); err != nil { + dl.Close() + return "", err + } + dl.Close() + if lr.N <= 0 { + return "", fmt.Errorf("downloaded zip file too large") + } + size := (maxSize + 1) - lr.N + if _, err := f.Seek(0, 0); err != nil { + return "", err + } + + // Translate from zip file we have to zip file we want. + zr, err := zip.NewReader(f, size) + if err != nil { + return "", err + } + f2, err := ioutil.TempFile(tmpdir, "go-codezip-") + if err != nil { + return "", err + } + + zw := zip.NewWriter(f2) + newName := f2.Name() + defer func() { + f2.Close() + if err != nil { + os.Remove(newName) + } + }() + if subdir != "" { + subdir += "/" + } + haveLICENSE := false + topPrefix := "" + haveGoMod := make(map[string]bool) + for _, zf := range zr.File { + if topPrefix == "" { + i := strings.Index(zf.Name, "/") + if i < 0 { + return "", fmt.Errorf("missing top-level directory prefix") + } + topPrefix = zf.Name[:i+1] + } + if !strings.HasPrefix(zf.Name, topPrefix) { + return "", fmt.Errorf("zip file contains more than one top-level directory") + } + dir, file := path.Split(zf.Name) + if file == "go.mod" { + haveGoMod[dir] = true + } + } + root := topPrefix + subdir + inSubmodule := func(name string) bool { + for { + dir, _ := path.Split(name) + if len(dir) <= len(root) { + return false + } + if haveGoMod[dir] { + return true + } + name = dir[:len(dir)-1] + } + } + for _, zf := range zr.File { + if topPrefix == "" { + i := strings.Index(zf.Name, "/") + if i < 0 { + return "", fmt.Errorf("missing top-level directory prefix") + } + topPrefix = zf.Name[:i+1] + } + if strings.HasSuffix(zf.Name, "/") { // drop directory dummy entries + continue + } + if !strings.HasPrefix(zf.Name, topPrefix) { + return "", fmt.Errorf("zip file contains more than one top-level directory") + } + name := strings.TrimPrefix(zf.Name, topPrefix) + if !strings.HasPrefix(name, subdir) { + continue + } + if name == ".hg_archival.txt" { + // Inserted by hg archive. + // Not correct to drop from other version control systems, but too bad. + continue + } + name = strings.TrimPrefix(name, subdir) + if isVendoredPackage(name) { + continue + } + if inSubmodule(zf.Name) { + continue + } + base := path.Base(name) + if strings.ToLower(base) == "go.mod" && base != "go.mod" { + return "", fmt.Errorf("zip file contains %s, want all lower-case go.mod", zf.Name) + } + if name == "LICENSE" { + haveLICENSE = true + } + size := int64(zf.UncompressedSize) + if size < 0 || maxSize < size { + return "", fmt.Errorf("module source tree too big") + } + maxSize -= size + + rc, err := zf.Open() + if err != nil { + return "", err + } + w, err := zw.Create(r.modPrefix(version) + "/" + name) + lr := &io.LimitedReader{R: rc, N: size + 1} + if _, err := io.Copy(w, lr); err != nil { + return "", err + } + if lr.N <= 0 { + return "", fmt.Errorf("individual file too large") + } + } + + if !haveLICENSE && subdir != "" { + data, err := r.code.ReadFile(rev, "LICENSE", codehost.MaxLICENSE) + if err == nil { + w, err := zw.Create(r.modPrefix(version) + "/LICENSE") + if err != nil { + return "", err + } + if _, err := w.Write(data); err != nil { + return "", err + } + } + } + if err := zw.Close(); err != nil { + return "", err + } + if err := f2.Close(); err != nil { + return "", err + } + + return f2.Name(), nil +} + +// hasPathPrefix reports whether the path s begins with the +// elements in prefix. +func hasPathPrefix(s, prefix string) bool { + switch { + default: + return false + case len(s) == len(prefix): + return s == prefix + case len(s) > len(prefix): + if prefix != "" && prefix[len(prefix)-1] == '/' { + return strings.HasPrefix(s, prefix) + } + return s[len(prefix)] == '/' && s[:len(prefix)] == prefix + } +} + +func isVendoredPackage(name string) bool { + var i int + if strings.HasPrefix(name, "vendor/") { + i += len("vendor/") + } else if j := strings.Index(name, "/vendor/"); j >= 0 { + i += len("/vendor/") + } else { + return false + } + return strings.Contains(name[i:], "/") +} diff --git a/libgo/go/cmd/go/internal/modfetch/coderepo_test.go b/libgo/go/cmd/go/internal/modfetch/coderepo_test.go new file mode 100644 index 00000000000..79b82786cb9 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/coderepo_test.go @@ -0,0 +1,643 @@ +// 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 ( + "archive/zip" + "internal/testenv" + "io" + "io/ioutil" + "log" + "os" + "reflect" + "strings" + "testing" + "time" + + "cmd/go/internal/modfetch/codehost" +) + +func TestMain(m *testing.M) { + os.Exit(testMain(m)) +} + +func testMain(m *testing.M) int { + dir, err := ioutil.TempDir("", "gitrepo-test-") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(dir) + + codehost.WorkRoot = dir + return m.Run() +} + +const ( + vgotest1git = "github.com/rsc/vgotest1" + vgotest1hg = "vcs-test.golang.org/hg/vgotest1.hg" +) + +var altVgotests = []string{ + vgotest1hg, +} + +var codeRepoTests = []struct { + path string + lookerr string + mpath string + rev string + err string + version string + name string + short string + time time.Time + gomod string + gomoderr string + zip []string + ziperr string +}{ + { + path: "github.com/rsc/vgotest1", + rev: "v0.0.0", + version: "v0.0.0", + name: "80d85c5d4d17598a0e9055e7c175a32b415d6128", + short: "80d85c5d4d17", + time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC), + zip: []string{ + "LICENSE", + "README.md", + "pkg/p.go", + }, + }, + { + path: "github.com/rsc/vgotest1", + rev: "v1.0.0", + version: "v1.0.0", + name: "80d85c5d4d17598a0e9055e7c175a32b415d6128", + short: "80d85c5d4d17", + time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC), + zip: []string{ + "LICENSE", + "README.md", + "pkg/p.go", + }, + }, + { + path: "github.com/rsc/vgotest1/v2", + rev: "v2.0.0", + version: "v2.0.0", + name: "45f53230a74ad275c7127e117ac46914c8126160", + short: "45f53230a74a", + time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC), + ziperr: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0", + }, + { + path: "github.com/rsc/vgotest1", + rev: "80d85c5", + version: "v1.0.0", + name: "80d85c5d4d17598a0e9055e7c175a32b415d6128", + short: "80d85c5d4d17", + time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC), + zip: []string{ + "LICENSE", + "README.md", + "pkg/p.go", + }, + }, + { + path: "github.com/rsc/vgotest1", + rev: "mytag", + version: "v1.0.0", + name: "80d85c5d4d17598a0e9055e7c175a32b415d6128", + short: "80d85c5d4d17", + time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC), + zip: []string{ + "LICENSE", + "README.md", + "pkg/p.go", + }, + }, + { + path: "github.com/rsc/vgotest1/v2", + rev: "45f53230a", + version: "v2.0.0", + name: "45f53230a74ad275c7127e117ac46914c8126160", + short: "45f53230a74a", + time: time.Date(2018, 7, 19, 1, 21, 27, 0, time.UTC), + gomoderr: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0", + ziperr: "missing github.com/rsc/vgotest1/go.mod and .../v2/go.mod at revision v2.0.0", + }, + { + path: "github.com/rsc/vgotest1/v54321", + rev: "80d85c5", + version: "v54321.0.0-20180219231006-80d85c5d4d17", + name: "80d85c5d4d17598a0e9055e7c175a32b415d6128", + short: "80d85c5d4d17", + time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC), + ziperr: "missing github.com/rsc/vgotest1/go.mod and .../v54321/go.mod at revision 80d85c5d4d17", + }, + { + path: "github.com/rsc/vgotest1/submod", + rev: "v1.0.0", + err: "unknown revision submod/v1.0.0", + }, + { + path: "github.com/rsc/vgotest1/submod", + rev: "v1.0.3", + err: "unknown revision submod/v1.0.3", + }, + { + path: "github.com/rsc/vgotest1/submod", + rev: "v1.0.4", + version: "v1.0.4", + name: "8afe2b2efed96e0880ecd2a69b98a53b8c2738b6", + short: "8afe2b2efed9", + time: time.Date(2018, 2, 19, 23, 12, 7, 0, time.UTC), + gomod: "module \"github.com/vgotest1/submod\" // submod/go.mod\n", + zip: []string{ + "go.mod", + "pkg/p.go", + "LICENSE", + }, + }, + { + path: "github.com/rsc/vgotest1", + rev: "v1.1.0", + version: "v1.1.0", + name: "b769f2de407a4db81af9c5de0a06016d60d2ea09", + short: "b769f2de407a", + time: time.Date(2018, 2, 19, 23, 13, 36, 0, time.UTC), + gomod: "module \"github.com/rsc/vgotest1\" // root go.mod\nrequire \"github.com/rsc/vgotest1/submod\" v1.0.5\n", + zip: []string{ + "LICENSE", + "README.md", + "go.mod", + "pkg/p.go", + }, + }, + { + path: "github.com/rsc/vgotest1/v2", + rev: "v2.0.1", + version: "v2.0.1", + name: "ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9", + short: "ea65f87c8f52", + time: time.Date(2018, 2, 19, 23, 14, 23, 0, time.UTC), + gomod: "module \"github.com/rsc/vgotest1/v2\" // root go.mod\n", + }, + { + path: "github.com/rsc/vgotest1/v2", + rev: "v2.0.3", + version: "v2.0.3", + name: "f18795870fb14388a21ef3ebc1d75911c8694f31", + short: "f18795870fb1", + time: time.Date(2018, 2, 19, 23, 16, 4, 0, time.UTC), + gomoderr: "github.com/rsc/vgotest1/v2/go.mod has non-.../v2 module path \"github.com/rsc/vgotest\" at revision v2.0.3", + }, + { + path: "github.com/rsc/vgotest1/v2", + rev: "v2.0.4", + version: "v2.0.4", + name: "1f863feb76bc7029b78b21c5375644838962f88d", + short: "1f863feb76bc", + time: time.Date(2018, 2, 20, 0, 3, 38, 0, time.UTC), + gomoderr: "github.com/rsc/vgotest1/go.mod and .../v2/go.mod both have .../v2 module paths at revision v2.0.4", + }, + { + path: "github.com/rsc/vgotest1/v2", + rev: "v2.0.5", + version: "v2.0.5", + name: "2f615117ce481c8efef46e0cc0b4b4dccfac8fea", + short: "2f615117ce48", + time: time.Date(2018, 2, 20, 0, 3, 59, 0, time.UTC), + gomod: "module \"github.com/rsc/vgotest1/v2\" // v2/go.mod\n", + }, + { + // redirect to github + path: "rsc.io/quote", + rev: "v1.0.0", + version: "v1.0.0", + name: "f488df80bcdbd3e5bafdc24ad7d1e79e83edd7e6", + short: "f488df80bcdb", + time: time.Date(2018, 2, 14, 0, 45, 20, 0, time.UTC), + gomod: "module \"rsc.io/quote\"\n", + }, + { + // redirect to static hosting proxy + path: "swtch.com/testmod", + rev: "v1.0.0", + version: "v1.0.0", + // NO name or short - we intentionally ignore those in the proxy protocol + time: time.Date(1972, 7, 18, 12, 34, 56, 0, time.UTC), + gomod: "module \"swtch.com/testmod\"\n", + }, + { + // redirect to googlesource + path: "golang.org/x/text", + rev: "4e4a3210bb", + version: "v0.3.1-0.20180208041248-4e4a3210bb54", + name: "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1", + short: "4e4a3210bb54", + time: time.Date(2018, 2, 8, 4, 12, 48, 0, time.UTC), + }, + { + path: "github.com/pkg/errors", + rev: "v0.8.0", + version: "v0.8.0", + name: "645ef00459ed84a119197bfb8d8205042c6df63d", + short: "645ef00459ed", + time: time.Date(2016, 9, 29, 1, 48, 1, 0, time.UTC), + }, + { + // package in subdirectory - custom domain + // In general we can't reject these definitively in Lookup, + // but gopkg.in is special. + path: "gopkg.in/yaml.v2/abc", + lookerr: "invalid module path \"gopkg.in/yaml.v2/abc\"", + }, + { + // package in subdirectory - github + // Because it's a package, Stat should fail entirely. + path: "github.com/rsc/quote/buggy", + rev: "c4d4236f", + err: "missing github.com/rsc/quote/buggy/go.mod at revision c4d4236f9242", + }, + { + path: "gopkg.in/yaml.v2", + rev: "d670f940", + version: "v2.0.0", + name: "d670f9405373e636a5a2765eea47fac0c9bc91a4", + short: "d670f9405373", + time: time.Date(2018, 1, 9, 11, 43, 31, 0, time.UTC), + gomod: "module gopkg.in/yaml.v2\n", + }, + { + path: "gopkg.in/check.v1", + rev: "20d25e280405", + version: "v1.0.0-20161208181325-20d25e280405", + name: "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec", + short: "20d25e280405", + time: time.Date(2016, 12, 8, 18, 13, 25, 0, time.UTC), + gomod: "module gopkg.in/check.v1\n", + }, + { + path: "gopkg.in/yaml.v2", + rev: "v2", + version: "v2.2.1", + name: "5420a8b6744d3b0345ab293f6fcba19c978f1183", + short: "5420a8b6744d", + time: time.Date(2018, 3, 28, 19, 50, 20, 0, time.UTC), + gomod: "module \"gopkg.in/yaml.v2\"\n\nrequire (\n\t\"gopkg.in/check.v1\" v0.0.0-20161208181325-20d25e280405\n)\n", + }, + { + path: "vcs-test.golang.org/go/mod/gitrepo1", + rev: "master", + version: "v1.2.4-annotated", + name: "ede458df7cd0fdca520df19a33158086a8a68e81", + short: "ede458df7cd0", + time: time.Date(2018, 4, 17, 19, 43, 22, 0, time.UTC), + gomod: "module vcs-test.golang.org/go/mod/gitrepo1\n", + }, + { + path: "gopkg.in/natefinch/lumberjack.v2", + rev: "latest", + version: "v2.0.0-20170531160350-a96e63847dc3", + name: "a96e63847dc3c67d17befa69c303767e2f84e54f", + short: "a96e63847dc3", + time: time.Date(2017, 5, 31, 16, 3, 50, 0, time.UTC), + gomod: "module gopkg.in/natefinch/lumberjack.v2\n", + }, + { + path: "gopkg.in/natefinch/lumberjack.v2", + // This repo has a v2.1 tag. + // We only allow semver references to tags that are fully qualified, as in v2.1.0. + // Because we can't record v2.1.0 (the actual tag is v2.1), we record a pseudo-version + // instead, same as if the tag were any other non-version-looking string. + // We use a v2 pseudo-version here because of the .v2 in the path, not because + // of the v2 in the rev. + rev: "v2.1", // non-canonical semantic version turns into pseudo-version + version: "v2.0.0-20170531160350-a96e63847dc3", + name: "a96e63847dc3c67d17befa69c303767e2f84e54f", + short: "a96e63847dc3", + time: time.Date(2017, 5, 31, 16, 3, 50, 0, time.UTC), + gomod: "module gopkg.in/natefinch/lumberjack.v2\n", + }, +} + +func TestCodeRepo(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tmpdir, err := ioutil.TempDir("", "vgo-modfetch-test-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + for _, tt := range codeRepoTests { + f := func(t *testing.T) { + repo, err := Lookup(tt.path) + if tt.lookerr != "" { + if err != nil && err.Error() == tt.lookerr { + return + } + t.Errorf("Lookup(%q): %v, want error %q", tt.path, err, tt.lookerr) + } + if err != nil { + t.Fatalf("Lookup(%q): %v", tt.path, err) + } + if tt.mpath == "" { + tt.mpath = tt.path + } + if mpath := repo.ModulePath(); mpath != tt.mpath { + t.Errorf("repo.ModulePath() = %q, want %q", mpath, tt.mpath) + } + info, err := repo.Stat(tt.rev) + if err != nil { + if tt.err != "" { + if !strings.Contains(err.Error(), tt.err) { + t.Fatalf("repoStat(%q): %v, wanted %q", tt.rev, err, tt.err) + } + return + } + t.Fatalf("repo.Stat(%q): %v", tt.rev, err) + } + if tt.err != "" { + t.Errorf("repo.Stat(%q): success, wanted error", tt.rev) + } + if info.Version != tt.version { + t.Errorf("info.Version = %q, want %q", info.Version, tt.version) + } + if info.Name != tt.name { + t.Errorf("info.Name = %q, want %q", info.Name, tt.name) + } + if info.Short != tt.short { + t.Errorf("info.Short = %q, want %q", info.Short, tt.short) + } + if !info.Time.Equal(tt.time) { + t.Errorf("info.Time = %v, want %v", info.Time, tt.time) + } + if tt.gomod != "" || tt.gomoderr != "" { + data, err := repo.GoMod(tt.version) + if err != nil && tt.gomoderr == "" { + t.Errorf("repo.GoMod(%q): %v", tt.version, err) + } else if err != nil && tt.gomoderr != "" { + if err.Error() != tt.gomoderr { + t.Errorf("repo.GoMod(%q): %v, want %q", tt.version, err, tt.gomoderr) + } + } else if tt.gomoderr != "" { + t.Errorf("repo.GoMod(%q) = %q, want error %q", tt.version, data, tt.gomoderr) + } else if string(data) != tt.gomod { + t.Errorf("repo.GoMod(%q) = %q, want %q", tt.version, data, tt.gomod) + } + } + if tt.zip != nil || tt.ziperr != "" { + zipfile, err := repo.Zip(tt.version, tmpdir) + if err != nil { + if tt.ziperr != "" { + if err.Error() == tt.ziperr { + return + } + t.Fatalf("repo.Zip(%q): %v, want error %q", tt.version, err, tt.ziperr) + } + t.Fatalf("repo.Zip(%q): %v", tt.version, err) + } + if tt.ziperr != "" { + t.Errorf("repo.Zip(%q): success, want error %q", tt.version, tt.ziperr) + } + prefix := tt.path + "@" + tt.version + "/" + z, err := zip.OpenReader(zipfile) + if err != nil { + t.Fatalf("open zip %s: %v", zipfile, err) + } + var names []string + for _, file := range z.File { + if !strings.HasPrefix(file.Name, prefix) { + t.Errorf("zip entry %v does not start with prefix %v", file.Name, prefix) + continue + } + names = append(names, file.Name[len(prefix):]) + } + z.Close() + if !reflect.DeepEqual(names, tt.zip) { + t.Fatalf("zip = %v\nwant %v\n", names, tt.zip) + } + } + } + t.Run(strings.Replace(tt.path, "/", "_", -1)+"/"+tt.rev, f) + if strings.HasPrefix(tt.path, vgotest1git) { + for _, alt := range altVgotests { + // Note: Communicating with f through tt; should be cleaned up. + old := tt + tt.path = alt + strings.TrimPrefix(tt.path, vgotest1git) + if strings.HasPrefix(tt.mpath, vgotest1git) { + tt.mpath = alt + strings.TrimPrefix(tt.mpath, vgotest1git) + } + var m map[string]string + if alt == vgotest1hg { + m = hgmap + } + tt.version = remap(tt.version, m) + tt.name = remap(tt.name, m) + tt.short = remap(tt.short, m) + tt.rev = remap(tt.rev, m) + tt.gomoderr = remap(tt.gomoderr, m) + tt.ziperr = remap(tt.ziperr, m) + t.Run(strings.Replace(tt.path, "/", "_", -1)+"/"+tt.rev, f) + tt = old + } + } + } +} + +var hgmap = map[string]string{ + "github.com/rsc/vgotest1/": "vcs-test.golang.org/hg/vgotest1.hg/", + "f18795870fb14388a21ef3ebc1d75911c8694f31": "a9ad6d1d14eb544f459f446210c7eb3b009807c6", + "ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9": "f1fc0f22021b638d073d31c752847e7bf385def7", + "b769f2de407a4db81af9c5de0a06016d60d2ea09": "92c7eb888b4fac17f1c6bd2e1060a1b881a3b832", + "8afe2b2efed96e0880ecd2a69b98a53b8c2738b6": "4e58084d459ae7e79c8c2264d0e8e9a92eb5cd44", + "2f615117ce481c8efef46e0cc0b4b4dccfac8fea": "879ea98f7743c8eff54f59a918f3a24123d1cf46", + "80d85c5d4d17598a0e9055e7c175a32b415d6128": "e125018e286a4b09061079a81e7b537070b7ff71", + "1f863feb76bc7029b78b21c5375644838962f88d": "bf63880162304a9337477f3858f5b7e255c75459", + "45f53230a74ad275c7127e117ac46914c8126160": "814fce58e83abd5bf2a13892e0b0e1198abefcd4", +} + +func remap(name string, m map[string]string) string { + if m[name] != "" { + return m[name] + } + if codehost.AllHex(name) { + for k, v := range m { + if strings.HasPrefix(k, name) { + return v[:len(name)] + } + } + } + for k, v := range m { + name = strings.Replace(name, k, v, -1) + if codehost.AllHex(k) { + name = strings.Replace(name, k[:12], v[:12], -1) + } + } + return name +} + +var codeRepoVersionsTests = []struct { + path string + prefix string + versions []string +}{ + { + path: "github.com/rsc/vgotest1", + versions: []string{"v0.0.0", "v0.0.1", "v1.0.0", "v1.0.1", "v1.0.2", "v1.0.3", "v1.1.0", "v2.0.0+incompatible"}, + }, + { + path: "github.com/rsc/vgotest1", + prefix: "v1.0", + versions: []string{"v1.0.0", "v1.0.1", "v1.0.2", "v1.0.3"}, + }, + { + path: "github.com/rsc/vgotest1/v2", + versions: []string{"v2.0.0", "v2.0.1", "v2.0.2", "v2.0.3", "v2.0.4", "v2.0.5", "v2.0.6"}, + }, + { + path: "swtch.com/testmod", + versions: []string{"v1.0.0", "v1.1.1"}, + }, + { + path: "gopkg.in/russross/blackfriday.v2", + versions: []string{"v2.0.0"}, + }, + { + path: "gopkg.in/natefinch/lumberjack.v2", + versions: nil, + }, +} + +func TestCodeRepoVersions(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tmpdir, err := ioutil.TempDir("", "vgo-modfetch-test-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + for _, tt := range codeRepoVersionsTests { + t.Run(strings.Replace(tt.path, "/", "_", -1), func(t *testing.T) { + repo, err := Lookup(tt.path) + if err != nil { + t.Fatalf("Lookup(%q): %v", tt.path, err) + } + list, err := repo.Versions(tt.prefix) + if err != nil { + t.Fatalf("Versions(%q): %v", tt.prefix, err) + } + if !reflect.DeepEqual(list, tt.versions) { + t.Fatalf("Versions(%q):\nhave %v\nwant %v", tt.prefix, list, tt.versions) + } + }) + } +} + +var latestTests = []struct { + path string + version string + err string +}{ + { + path: "github.com/rsc/empty", + err: "no commits", + }, + { + path: "github.com/rsc/vgotest1", + version: "v0.0.0-20180219223237-a08abb797a67", + }, + { + path: "github.com/rsc/vgotest1/subdir", + err: "missing github.com/rsc/vgotest1/subdir/go.mod at revision a08abb797a67", + }, + { + path: "swtch.com/testmod", + version: "v1.1.1", + }, +} + +func TestLatest(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + tmpdir, err := ioutil.TempDir("", "vgo-modfetch-test-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + for _, tt := range latestTests { + name := strings.Replace(tt.path, "/", "_", -1) + t.Run(name, func(t *testing.T) { + repo, err := Lookup(tt.path) + if err != nil { + t.Fatalf("Lookup(%q): %v", tt.path, err) + } + info, err := repo.Latest() + if err != nil { + if tt.err != "" { + if err.Error() == tt.err { + return + } + t.Fatalf("Latest(): %v, want %q", err, tt.err) + } + t.Fatalf("Latest(): %v", err) + } + if tt.err != "" { + t.Fatalf("Latest() = %v, want error %q", info.Version, tt.err) + } + if info.Version != tt.version { + t.Fatalf("Latest() = %v, want %v", info.Version, tt.version) + } + }) + } +} + +// fixedTagsRepo is a fake codehost.Repo that returns a fixed list of tags +type fixedTagsRepo struct { + tags []string +} + +func (ch *fixedTagsRepo) Tags(string) ([]string, error) { return ch.tags, nil } +func (ch *fixedTagsRepo) Latest() (*codehost.RevInfo, error) { panic("not impl") } +func (ch *fixedTagsRepo) ReadFile(string, string, int64) ([]byte, error) { panic("not impl") } +func (ch *fixedTagsRepo) ReadFileRevs([]string, string, int64) (map[string]*codehost.FileRev, error) { + panic("not impl") +} +func (ch *fixedTagsRepo) ReadZip(string, string, int64) (io.ReadCloser, string, error) { + panic("not impl") +} +func (ch *fixedTagsRepo) RecentTag(string, string) (string, error) { + panic("not impl") +} +func (ch *fixedTagsRepo) Stat(string) (*codehost.RevInfo, error) { panic("not impl") } + +func TestNonCanonicalSemver(t *testing.T) { + root := "golang.org/x/issue24476" + ch := &fixedTagsRepo{ + tags: []string{ + "", "huh?", "1.0.1", + // what about "version 1 dot dogcow"? + "v1.🐕.🐄", + "v1", "v0.1", + // and one normal one that should pass through + "v1.0.1", + }, + } + + cr, err := newCodeRepo(ch, root, root) + if err != nil { + t.Fatal(err) + } + + v, err := cr.Versions("") + if err != nil { + t.Fatal(err) + } + if len(v) != 1 || v[0] != "v1.0.1" { + t.Fatal("unexpected versions returned:", v) + } +} diff --git a/libgo/go/cmd/go/internal/modfetch/fetch.go b/libgo/go/cmd/go/internal/modfetch/fetch.go new file mode 100644 index 00000000000..2e26bac434d --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/fetch.go @@ -0,0 +1,365 @@ +// 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 ( + "archive/zip" + "bytes" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "sort" + "strings" + "sync" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/dirhash" + "cmd/go/internal/module" + "cmd/go/internal/par" +) + +var downloadCache par.Cache + +// Download downloads the specific module version to the +// local download cache and returns the name of the directory +// corresponding to the root of the module's file tree. +func Download(mod module.Version) (dir string, err error) { + if PkgMod == "" { + // Do not download to current directory. + return "", fmt.Errorf("missing modfetch.PkgMod") + } + + // The par.Cache here avoids duplicate work but also + // avoids conflicts from simultaneous calls by multiple goroutines + // for the same version. + type cached struct { + dir string + err error + } + c := downloadCache.Do(mod, func() interface{} { + dir, err := DownloadDir(mod) + if err != nil { + return cached{"", err} + } + if files, _ := ioutil.ReadDir(dir); len(files) == 0 { + zipfile, err := DownloadZip(mod) + if err != nil { + return cached{"", err} + } + modpath := mod.Path + "@" + mod.Version + if err := Unzip(dir, zipfile, modpath, 0); err != nil { + fmt.Fprintf(os.Stderr, "-> %s\n", err) + return cached{"", err} + } + } + checkSum(mod) + return cached{dir, nil} + }).(cached) + return c.dir, c.err +} + +var downloadZipCache par.Cache + +// DownloadZip downloads the specific module version to the +// local zip cache and returns the name of the zip file. +func DownloadZip(mod module.Version) (zipfile string, err error) { + // The par.Cache here avoids duplicate work but also + // avoids conflicts from simultaneous calls by multiple goroutines + // for the same version. + type cached struct { + zipfile string + err error + } + c := downloadZipCache.Do(mod, func() interface{} { + zipfile, err := CachePath(mod, "zip") + if err != nil { + return cached{"", err} + } + if _, err := os.Stat(zipfile); err == nil { + // Use it. + // This should only happen if the mod/cache directory is preinitialized + // or if pkg/mod/path was removed but not pkg/mod/cache/download. + if cfg.CmdName != "mod download" { + fmt.Fprintf(os.Stderr, "go: extracting %s %s\n", mod.Path, mod.Version) + } + } else { + if err := os.MkdirAll(filepath.Dir(zipfile), 0777); err != nil { + return cached{"", err} + } + if cfg.CmdName != "mod download" { + fmt.Fprintf(os.Stderr, "go: downloading %s %s\n", mod.Path, mod.Version) + } + if err := downloadZip(mod, zipfile); err != nil { + return cached{"", err} + } + } + return cached{zipfile, nil} + }).(cached) + return c.zipfile, c.err +} + +func downloadZip(mod module.Version, target string) error { + repo, err := Lookup(mod.Path) + if err != nil { + return err + } + tmpfile, err := repo.Zip(mod.Version, os.TempDir()) + if err != nil { + return err + } + defer os.Remove(tmpfile) + + // Double-check zip file looks OK. + z, err := zip.OpenReader(tmpfile) + if err != nil { + return err + } + prefix := mod.Path + "@" + mod.Version + for _, f := range z.File { + if !strings.HasPrefix(f.Name, prefix) { + z.Close() + return fmt.Errorf("zip for %s has unexpected file %s", prefix[:len(prefix)-1], f.Name) + } + } + z.Close() + + hash, err := dirhash.HashZip(tmpfile, dirhash.DefaultHash) + if err != nil { + return err + } + checkOneSum(mod, hash) // check before installing the zip file + r, err := os.Open(tmpfile) + if err != nil { + return err + } + defer r.Close() + w, err := os.Create(target) + if err != nil { + return err + } + if _, err := io.Copy(w, r); err != nil { + w.Close() + return fmt.Errorf("copying: %v", err) + } + if err := w.Close(); err != nil { + return err + } + return ioutil.WriteFile(target+"hash", []byte(hash), 0666) +} + +var GoSumFile string // path to go.sum; set by package modload + +var goSum struct { + mu sync.Mutex + m map[module.Version][]string // content of go.sum file (+ go.modverify if present) + enabled bool // whether to use go.sum at all + modverify string // path to go.modverify, to be deleted +} + +// initGoSum initializes the go.sum data. +// It reports whether use of go.sum is now enabled. +// The goSum lock must be held. +func initGoSum() bool { + if GoSumFile == "" { + return false + } + if goSum.m != nil { + return true + } + + goSum.m = make(map[module.Version][]string) + data, err := ioutil.ReadFile(GoSumFile) + if err != nil && !os.IsNotExist(err) { + base.Fatalf("go: %v", err) + } + goSum.enabled = true + readGoSum(GoSumFile, data) + + // Add old go.modverify file. + // We'll delete go.modverify in WriteGoSum. + alt := strings.TrimSuffix(GoSumFile, ".sum") + ".modverify" + if data, err := ioutil.ReadFile(alt); err == nil { + readGoSum(alt, data) + goSum.modverify = alt + } + return true +} + +// emptyGoModHash is the hash of a 1-file tree containing a 0-length go.mod. +// A bug caused us to write these into go.sum files for non-modules. +// We detect and remove them. +const emptyGoModHash = "h1:G7mAYYxgmS0lVkHyy2hEOLQCFB0DlQFTMLWggykrydY=" + +// readGoSum parses data, which is the content of file, +// and adds it to goSum.m. The goSum lock must be held. +func readGoSum(file string, data []byte) { + lineno := 0 + for len(data) > 0 { + var line []byte + lineno++ + i := bytes.IndexByte(data, '\n') + if i < 0 { + line, data = data, nil + } else { + line, data = data[:i], data[i+1:] + } + f := strings.Fields(string(line)) + if len(f) == 0 { + // blank line; skip it + continue + } + if len(f) != 3 { + base.Fatalf("go: malformed go.sum:\n%s:%d: wrong number of fields %v", file, lineno, len(f)) + } + if f[2] == emptyGoModHash { + // Old bug; drop it. + continue + } + mod := module.Version{Path: f[0], Version: f[1]} + goSum.m[mod] = append(goSum.m[mod], f[2]) + } +} + +// checkSum checks the given module's checksum. +func checkSum(mod module.Version) { + if PkgMod == "" { + // Do not use current directory. + return + } + + // Do the file I/O before acquiring the go.sum lock. + ziphash, err := CachePath(mod, "ziphash") + if err != nil { + base.Fatalf("go: verifying %s@%s: %v", mod.Path, mod.Version, err) + } + data, err := ioutil.ReadFile(ziphash) + if err != nil { + if os.IsNotExist(err) { + // This can happen if someone does rm -rf GOPATH/src/cache/download. So it goes. + return + } + base.Fatalf("go: verifying %s@%s: %v", mod.Path, mod.Version, err) + } + h := strings.TrimSpace(string(data)) + if !strings.HasPrefix(h, "h1:") { + base.Fatalf("go: verifying %s@%s: unexpected ziphash: %q", mod.Path, mod.Version, h) + } + + checkOneSum(mod, h) +} + +// goModSum returns the checksum for the go.mod contents. +func goModSum(data []byte) (string, error) { + return dirhash.Hash1([]string{"go.mod"}, func(string) (io.ReadCloser, error) { + return ioutil.NopCloser(bytes.NewReader(data)), nil + }) +} + +// checkGoMod checks the given module's go.mod checksum; +// data is the go.mod content. +func checkGoMod(path, version string, data []byte) { + h, err := goModSum(data) + if err != nil { + base.Fatalf("go: verifying %s %s go.mod: %v", path, version, err) + } + + checkOneSum(module.Version{Path: path, Version: version + "/go.mod"}, h) +} + +// checkOneSum checks that the recorded hash for mod is h. +func checkOneSum(mod module.Version, h string) { + goSum.mu.Lock() + defer goSum.mu.Unlock() + if !initGoSum() { + return + } + + for _, vh := range goSum.m[mod] { + if h == vh { + return + } + if strings.HasPrefix(vh, "h1:") { + base.Fatalf("go: verifying %s@%s: checksum mismatch\n\tdownloaded: %v\n\tgo.sum: %v", mod.Path, mod.Version, h, vh) + } + } + if len(goSum.m[mod]) > 0 { + fmt.Fprintf(os.Stderr, "warning: verifying %s@%s: unknown hashes in go.sum: %v; adding %v", mod.Path, mod.Version, strings.Join(goSum.m[mod], ", "), h) + } + goSum.m[mod] = append(goSum.m[mod], h) +} + +// Sum returns the checksum for the downloaded copy of the given module, +// if present in the download cache. +func Sum(mod module.Version) string { + if PkgMod == "" { + // Do not use current directory. + return "" + } + + ziphash, err := CachePath(mod, "ziphash") + if err != nil { + return "" + } + data, err := ioutil.ReadFile(ziphash) + if err != nil { + return "" + } + return strings.TrimSpace(string(data)) +} + +// WriteGoSum writes the go.sum file if it needs to be updated. +func WriteGoSum() { + goSum.mu.Lock() + defer goSum.mu.Unlock() + if !initGoSum() { + return + } + + var mods []module.Version + for m := range goSum.m { + mods = append(mods, m) + } + module.Sort(mods) + var buf bytes.Buffer + for _, m := range mods { + list := goSum.m[m] + sort.Strings(list) + for _, h := range list { + fmt.Fprintf(&buf, "%s %s %s\n", m.Path, m.Version, h) + } + } + + data, _ := ioutil.ReadFile(GoSumFile) + if !bytes.Equal(data, buf.Bytes()) { + if err := ioutil.WriteFile(GoSumFile, buf.Bytes(), 0666); err != nil { + base.Fatalf("go: writing go.sum: %v", err) + } + } + + if goSum.modverify != "" { + os.Remove(goSum.modverify) + } +} + +// TrimGoSum trims go.sum to contain only the modules for which keep[m] is true. +func TrimGoSum(keep map[module.Version]bool) { + goSum.mu.Lock() + defer goSum.mu.Unlock() + if !initGoSum() { + return + } + + for m := range goSum.m { + // If we're keeping x@v we also keep x@v/go.mod. + // Map x@v/go.mod back to x@v for the keep lookup. + noGoMod := module.Version{Path: m.Path, Version: strings.TrimSuffix(m.Version, "/go.mod")} + if !keep[m] && !keep[noGoMod] { + delete(goSum.m, m) + } + } +} diff --git a/libgo/go/cmd/go/internal/modfetch/noweb.go b/libgo/go/cmd/go/internal/modfetch/noweb.go new file mode 100644 index 00000000000..9d713dcc669 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/noweb.go @@ -0,0 +1,24 @@ +// 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 cmd_go_bootstrap + +package modfetch + +import ( + "fmt" + "io" +) + +func webGetGoGet(url string, body *io.ReadCloser) error { + return fmt.Errorf("no network in go_bootstrap") +} + +func webGetBytes(url string, body *[]byte) error { + return fmt.Errorf("no network in go_bootstrap") +} + +func webGetBody(url string, body *io.ReadCloser) error { + return fmt.Errorf("no network in go_bootstrap") +} diff --git a/libgo/go/cmd/go/internal/modfetch/proxy.go b/libgo/go/cmd/go/internal/modfetch/proxy.go new file mode 100644 index 00000000000..5f856b80d2e --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/proxy.go @@ -0,0 +1,252 @@ +// 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 ( + "encoding/json" + "fmt" + "io" + "io/ioutil" + "net/url" + "os" + "strings" + "time" + + "cmd/go/internal/base" + "cmd/go/internal/modfetch/codehost" + "cmd/go/internal/module" + "cmd/go/internal/semver" +) + +var HelpGoproxy = &base.Command{ + UsageLine: "goproxy", + Short: "module proxy protocol", + Long: ` +The go command by default downloads modules from version control systems +directly, just as 'go get' always has. The GOPROXY environment variable allows +further control over the download source. If GOPROXY is unset, is the empty string, +or is the string "direct", downloads use the default direct connection to version +control systems. Setting GOPROXY to "off" disallows downloading modules from +any source. Otherwise, GOPROXY is expected to be the URL of a module proxy, +in which case the go command will fetch all modules from that proxy. +No matter the source of the modules, downloaded modules must match existing +entries in go.sum (see 'go help modules' for discussion of verification). + +A Go module proxy is any web server that can respond to GET requests for +URLs of a specified form. The requests have no query parameters, so even +a site serving from a fixed file system (including a file:/// URL) +can be a module proxy. + +The GET requests sent to a Go module proxy are: + +GET $GOPROXY//@v/list returns a list of all known versions of the +given module, one per line. + +GET $GOPROXY//@v/.info returns JSON-formatted metadata +about that version of the given module. + +GET $GOPROXY//@v/.mod returns the go.mod file +for that version of the given module. + +GET $GOPROXY//@v/.zip returns the zip archive +for that version of the given module. + +To avoid problems when serving from case-sensitive file systems, +the and elements are case-encoded, replacing every +uppercase letter with an exclamation mark followed by the corresponding +lower-case letter: github.com/Azure encodes as github.com/!azure. + +The JSON-formatted metadata about a given module corresponds to +this Go data structure, which may be expanded in the future: + + type Info struct { + Version string // version string + Time time.Time // commit time + } + +The zip archive for a specific version of a given module is a +standard zip file that contains the file tree corresponding +to the module's source code and related files. The archive uses +slash-separated paths, and every file path in the archive must +begin with @/, where the module and version are +substituted directly, not case-encoded. The root of the module +file tree corresponds to the @/ prefix in the +archive. + +Even when downloading directly from version control systems, +the go command synthesizes explicit info, mod, and zip files +and stores them in its local cache, $GOPATH/pkg/mod/cache/download, +the same as if it had downloaded them directly from a proxy. +The cache layout is the same as the proxy URL space, so +serving $GOPATH/pkg/mod/cache/download at (or copying it to) +https://example.com/proxy would let other users access those +cached module versions with GOPROXY=https://example.com/proxy. +`, +} + +var proxyURL = os.Getenv("GOPROXY") + +func lookupProxy(path string) (Repo, error) { + if strings.Contains(proxyURL, ",") { + return nil, fmt.Errorf("invalid $GOPROXY setting: cannot have comma") + } + u, err := url.Parse(proxyURL) + if err != nil || u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "file" { + // Don't echo $GOPROXY back in case it has user:password in it (sigh). + return nil, fmt.Errorf("invalid $GOPROXY setting: malformed URL or invalid scheme (must be http, https, file)") + } + return newProxyRepo(u.String(), path) +} + +type proxyRepo struct { + url string + path string +} + +func newProxyRepo(baseURL, path string) (Repo, error) { + enc, err := module.EncodePath(path) + if err != nil { + return nil, err + } + return &proxyRepo{strings.TrimSuffix(baseURL, "/") + "/" + pathEscape(enc), path}, nil +} + +func (p *proxyRepo) ModulePath() string { + return p.path +} + +func (p *proxyRepo) Versions(prefix string) ([]string, error) { + var data []byte + err := webGetBytes(p.url+"/@v/list", &data) + if err != nil { + return nil, err + } + 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) { + list = append(list, f[0]) + } + } + SortVersions(list) + return list, nil +} + +func (p *proxyRepo) latest() (*RevInfo, error) { + var data []byte + err := webGetBytes(p.url+"/@v/list", &data) + if err != nil { + return nil, err + } + var best time.Time + var bestVersion string + for _, line := range strings.Split(string(data), "\n") { + f := strings.Fields(line) + if len(f) >= 2 && semver.IsValid(f[0]) { + ft, err := time.Parse(time.RFC3339, f[1]) + if err == nil && best.Before(ft) { + best = ft + bestVersion = f[0] + } + } + } + if bestVersion == "" { + return nil, fmt.Errorf("no commits") + } + info := &RevInfo{ + Version: bestVersion, + Name: bestVersion, + Short: bestVersion, + Time: best, + } + return info, nil +} + +func (p *proxyRepo) Stat(rev string) (*RevInfo, error) { + var data []byte + encRev, err := module.EncodeVersion(rev) + if err != nil { + return nil, err + } + err = webGetBytes(p.url+"/@v/"+pathEscape(encRev)+".info", &data) + if err != nil { + return nil, err + } + info := new(RevInfo) + if err := json.Unmarshal(data, info); err != nil { + return nil, err + } + return info, nil +} + +func (p *proxyRepo) Latest() (*RevInfo, error) { + var data []byte + u := p.url + "/@latest" + err := webGetBytes(u, &data) + if err != nil { + // TODO return err if not 404 + return p.latest() + } + info := new(RevInfo) + if err := json.Unmarshal(data, info); err != nil { + return nil, err + } + return info, nil +} + +func (p *proxyRepo) GoMod(version string) ([]byte, error) { + var data []byte + encVer, err := module.EncodeVersion(version) + if err != nil { + return nil, err + } + err = webGetBytes(p.url+"/@v/"+pathEscape(encVer)+".mod", &data) + if err != nil { + return nil, err + } + return data, nil +} + +func (p *proxyRepo) Zip(version string, tmpdir string) (tmpfile string, err error) { + var body io.ReadCloser + encVer, err := module.EncodeVersion(version) + if err != nil { + return "", err + } + err = webGetBody(p.url+"/@v/"+pathEscape(encVer)+".zip", &body) + if err != nil { + return "", err + } + defer body.Close() + + // Spool to local file. + f, err := ioutil.TempFile(tmpdir, "go-proxy-download-") + if err != nil { + return "", err + } + defer f.Close() + maxSize := int64(codehost.MaxZipFile) + lr := &io.LimitedReader{R: body, N: maxSize + 1} + if _, err := io.Copy(f, lr); err != nil { + os.Remove(f.Name()) + return "", err + } + if lr.N <= 0 { + os.Remove(f.Name()) + return "", fmt.Errorf("downloaded zip file too large") + } + if err := f.Close(); err != nil { + os.Remove(f.Name()) + return "", err + } + return f.Name(), nil +} + +// pathEscape escapes s so it can be used in a path. +// That is, it escapes things like ? and # (which really shouldn't appear anyway). +// It does not escape / to %2F: our REST API is designed so that / can be left as is. +func pathEscape(s string) string { + return strings.Replace(url.PathEscape(s), "%2F", "/", -1) +} diff --git a/libgo/go/cmd/go/internal/modfetch/pseudo.go b/libgo/go/cmd/go/internal/modfetch/pseudo.go new file mode 100644 index 00000000000..32c7bf883be --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/pseudo.go @@ -0,0 +1,129 @@ +// 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. + +// Pseudo-versions +// +// Code authors are expected to tag the revisions they want users to use, +// including prereleases. However, not all authors tag versions at all, +// and not all commits a user might want to try will have tags. +// A pseudo-version is a version with a special form that allows us to +// address an untagged commit and order that version with respect to +// other versions we might encounter. +// +// A pseudo-version takes one of the general forms: +// +// (1) vX.0.0-yyyymmddhhmmss-abcdef123456 +// (2) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456 +// (3) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456+incompatible +// (4) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456 +// (5) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456+incompatible +// +// If there is no recently tagged version with the right major version vX, +// then form (1) is used, creating a space of pseudo-versions at the bottom +// of the vX version range, less than any tagged version, including the unlikely v0.0.0. +// +// If the most recent tagged version before the target commit is vX.Y.Z or vX.Y.Z+incompatible, +// then the pseudo-version uses form (2) or (3), making it a prerelease for the next +// possible semantic version after vX.Y.Z. The leading 0 segment in the prerelease string +// ensures that the pseudo-version compares less than possible future explicit prereleases +// like vX.Y.(Z+1)-rc1 or vX.Y.(Z+1)-1. +// +// 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 + +import ( + "cmd/go/internal/semver" + "fmt" + "regexp" + "strings" + "time" +) + +// 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, +// and revision identifier (usually a 12-byte commit hash prefix). +func PseudoVersion(major, older string, t time.Time, rev string) string { + if major == "" { + major = "v0" + } + major = strings.TrimSuffix(major, "-unstable") // make gopkg.in/macaroon-bakery.v2-unstable use "v2" + segment := fmt.Sprintf("%s-%s", t.UTC().Format("20060102150405"), rev) + build := semver.Build(older) + older = semver.Canonical(older) + if older == "" { + return major + ".0.0-" + segment // form (1) + } + if semver.Prerelease(older) != "" { + return older + ".0." + segment + build // form (4), (5) + } + + // Form (2), (3). + // Extract patch from vMAJOR.MINOR.PATCH + v := older[:len(older)] + i := strings.LastIndex(v, ".") + 1 + v, patch := v[:i], v[i:] + + // Increment PATCH by adding 1 to decimal: + // scan right to left turning 9s to 0s until you find a digit to increment. + // (Number might exceed int64, but math/big is overkill.) + digits := []byte(patch) + for i = len(digits) - 1; i >= 0 && digits[i] == '9'; i-- { + digits[i] = '0' + } + if i >= 0 { + digits[i]++ + } else { + // digits is all zeros + digits[0] = '1' + digits = append(digits, '0') + } + patch = string(digits) + + // Reassemble. + return v + patch + "-0." + segment + build +} + +var pseudoVersionRE = regexp.MustCompile(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+incompatible)?$`) + +// IsPseudoVersion reports whether v is a pseudo-version. +func IsPseudoVersion(v string) bool { + return strings.Count(v, "-") >= 2 && semver.IsValid(v) && pseudoVersionRE.MatchString(v) +} + +// PseudoVersionTime returns the time stamp of the pseudo-version v. +// It returns an error if v is not a pseudo-version or if the time stamp +// embedded in the pseudo-version is not a valid time. +func PseudoVersionTime(v string) (time.Time, error) { + timestamp, _, err := parsePseudoVersion(v) + t, err := time.Parse("20060102150405", timestamp) + if err != nil { + return time.Time{}, fmt.Errorf("pseudo-version with malformed time %s: %q", timestamp, v) + } + return t, nil +} + +// PseudoVersionRev returns the revision identifier of the pseudo-version v. +// It returns an error if v is not a pseudo-version. +func PseudoVersionRev(v string) (rev string, err error) { + _, rev, err = parsePseudoVersion(v) + return +} + +func parsePseudoVersion(v string) (timestamp, rev string, err error) { + if !IsPseudoVersion(v) { + return "", "", fmt.Errorf("malformed pseudo-version %q", v) + } + v = strings.TrimSuffix(v, "+incompatible") + j := strings.LastIndex(v, "-") + v, rev = v[:j], v[j+1:] + i := strings.LastIndex(v, "-") + if j := strings.LastIndex(v, "."); j > i { + timestamp = v[j+1:] + } else { + timestamp = v[i+1:] + } + return timestamp, rev, nil +} diff --git a/libgo/go/cmd/go/internal/modfetch/pseudo_test.go b/libgo/go/cmd/go/internal/modfetch/pseudo_test.go new file mode 100644 index 00000000000..3c2fa514689 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/pseudo_test.go @@ -0,0 +1,74 @@ +// 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"}, +} + +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 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, "") + } + } +} diff --git a/libgo/go/cmd/go/internal/modfetch/repo.go b/libgo/go/cmd/go/internal/modfetch/repo.go new file mode 100644 index 00000000000..0ea8c1f0e35 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/repo.go @@ -0,0 +1,363 @@ +// 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 ( + "fmt" + "os" + "sort" + "time" + + "cmd/go/internal/cfg" + "cmd/go/internal/get" + "cmd/go/internal/modfetch/codehost" + "cmd/go/internal/par" + "cmd/go/internal/semver" + web "cmd/go/internal/web" +) + +const traceRepo = false // trace all repo actions, for debugging + +// A Repo represents a repository storing all versions of a single module. +// It must be safe for simultaneous use by multiple goroutines. +type Repo interface { + // ModulePath returns the module path. + ModulePath() string + + // Versions lists all known versions with the given prefix. + // Pseudo-versions are not included. + // Versions should be returned sorted in semver order + // (implementations can use SortVersions). + Versions(prefix string) (tags []string, err error) + + // Stat returns information about the revision rev. + // A revision can be any identifier known to the underlying service: + // commit hash, branch, tag, and so on. + Stat(rev string) (*RevInfo, error) + + // Latest returns the latest revision on the default branch, + // whatever that means in the underlying source code repository. + // It is only used when there are no tagged versions. + Latest() (*RevInfo, error) + + // GoMod returns the go.mod file for the given version. + GoMod(version string) (data []byte, err error) + + // Zip downloads a zip file for the given version + // to a new file in a given temporary directory. + // It returns the name of the new file. + // The caller should remove the file when finished with it. + Zip(version, tmpdir string) (tmpfile string, err error) +} + +// A Rev describes a single revision in a module repository. +type RevInfo struct { + Version string // version string + Time time.Time // commit time + + // These fields are used for Stat of arbitrary rev, + // but they are not recorded when talking about module versions. + Name string `json:"-"` // complete ID in underlying repository + Short string `json:"-"` // shortened ID, for use in pseudo-version +} + +// Re: module paths, import paths, repository roots, and lookups +// +// A module is a collection of Go packages stored in a file tree +// with a go.mod file at the root of the tree. +// The go.mod defines the module path, which is the import path +// corresponding to the root of the file tree. +// The import path of a directory within that file tree is the module path +// joined with the name of the subdirectory relative to the root. +// +// For example, the module with path rsc.io/qr corresponds to the +// file tree in the repository https://github.com/rsc/qr. +// That file tree has a go.mod that says "module rsc.io/qr". +// The package in the root directory has import path "rsc.io/qr". +// The package in the gf256 subdirectory has import path "rsc.io/qr/gf256". +// In this example, "rsc.io/qr" is both a module path and an import path. +// But "rsc.io/qr/gf256" is only an import path, not a module path: +// it names an importable package, but not a module. +// +// As a special case to incorporate code written before modules were +// introduced, if a path p resolves using the pre-module "go get" lookup +// to the root of a source code repository without a go.mod file, +// that repository is treated as if it had a go.mod in its root directory +// declaring module path p. (The go.mod is further considered to +// contain requirements corresponding to any legacy version +// tracking format such as Gopkg.lock, vendor/vendor.conf, and so on.) +// +// The presentation so far ignores the fact that a source code repository +// has many different versions of a file tree, and those versions may +// differ in whether a particular go.mod exists and what it contains. +// In fact there is a well-defined mapping only from a module path, version +// pair - often written path@version - to a particular file tree. +// For example rsc.io/qr@v0.1.0 depends on the "implicit go.mod at root of +// repository" rule, while rsc.io/qr@v0.2.0 has an explicit go.mod. +// Because the "go get" import paths rsc.io/qr and github.com/rsc/qr +// both redirect to the Git repository https://github.com/rsc/qr, +// github.com/rsc/qr@v0.1.0 is the same file tree as rsc.io/qr@v0.1.0 +// but a different module (a different name). In contrast, since v0.2.0 +// of that repository has an explicit go.mod that declares path rsc.io/qr, +// github.com/rsc/qr@v0.2.0 is an invalid module path, version pair. +// Before modules, import comments would have had the same effect. +// +// The set of import paths associated with a given module path is +// clearly not fixed: at the least, new directories with new import paths +// can always be added. But another potential operation is to split a +// subtree out of a module into its own module. If done carefully, +// this operation can be done while preserving compatibility for clients. +// For example, suppose that we want to split rsc.io/qr/gf256 into its +// own module, so that there would be two modules rsc.io/qr and rsc.io/qr/gf256. +// Then we can simultaneously issue rsc.io/qr v0.3.0 (dropping the gf256 subdirectory) +// and rsc.io/qr/gf256 v0.1.0, including in their respective go.mod +// cyclic requirements pointing at each other: rsc.io/qr v0.3.0 requires +// rsc.io/qr/gf256 v0.1.0 and vice versa. Then a build can be +// using an older rsc.io/qr module that includes the gf256 package, but if +// it adds a requirement on either the newer rsc.io/qr or the newer +// rsc.io/qr/gf256 module, it will automatically add the requirement +// on the complementary half, ensuring both that rsc.io/qr/gf256 is +// available for importing by the build and also that it is only defined +// by a single module. The gf256 package could move back into the +// original by another simultaneous release of rsc.io/qr v0.4.0 including +// the gf256 subdirectory and an rsc.io/qr/gf256 v0.2.0 with no code +// in its root directory, along with a new requirement cycle. +// The ability to shift module boundaries in this way is expected to be +// important in large-scale program refactorings, similar to the ones +// described in https://talks.golang.org/2016/refactor.article. +// +// The possibility of shifting module boundaries reemphasizes +// that you must know both the module path and its version +// to determine the set of packages provided directly by that module. +// +// On top of all this, it is possible for a single code repository +// to contain multiple modules, either in branches or subdirectories, +// as a limited kind of monorepo. For example rsc.io/qr/v2, +// the v2.x.x continuation of rsc.io/qr, is expected to be found +// in v2-tagged commits in https://github.com/rsc/qr, either +// in the root or in a v2 subdirectory, disambiguated by go.mod. +// Again the precise file tree corresponding to a module +// depends on which version we are considering. +// +// It is also possible for the underlying repository to change over time, +// without changing the module path. If I copy the github repo over +// to https://bitbucket.org/rsc/qr and update https://rsc.io/qr?go-get=1, +// then clients of all versions should start fetching from bitbucket +// instead of github. That is, in contrast to the exact file tree, +// the location of the source code repository associated with a module path +// does not depend on the module version. (This is by design, as the whole +// point of these redirects is to allow package authors to establish a stable +// name that can be updated as code moves from one service to another.) +// +// All of this is important background for the lookup APIs defined in this +// file. +// +// The Lookup function takes a module path and returns a Repo representing +// that module path. Lookup can do only a little with the path alone. +// It can check that the path is well-formed (see semver.CheckPath) +// 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 Import function takes an import path found in source code and +// determines which module to add to the requirement list to satisfy +// that import. It checks successive truncations of the import path +// to determine possible modules and stops when it finds a module +// in which the latest version satisfies the import path. +// +// 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 + +// Lookup returns the module with the given module path. +// A successful return does not guarantee that the module +// has any defined versions. +func Lookup(path string) (Repo, error) { + if traceRepo { + defer logCall("Lookup(%q)", path)() + } + + type cached struct { + r Repo + err error + } + c := lookupCache.Do(path, func() interface{} { + r, err := lookup(path) + if err == nil { + if traceRepo { + r = newLoggingRepo(r) + } + r = newCachingRepo(r) + } + return cached{r, err} + }).(cached) + + return c.r, c.err +} + +// lookup returns the module with the given module path. +func lookup(path string) (r Repo, err error) { + if cfg.BuildMod == "vendor" { + return nil, fmt.Errorf("module lookup disabled by -mod=%s", cfg.BuildMod) + } + if proxyURL == "off" { + return nil, fmt.Errorf("module lookup disabled by GOPROXY=%s", proxyURL) + } + if proxyURL != "" && proxyURL != "direct" { + return lookupProxy(path) + } + + security := web.Secure + if get.Insecure { + security = web.Insecure + } + rr, err := get.RepoRootForImportPath(path, get.PreferMod, security) + if err != nil { + // We don't know where to find code for a module with this path. + return nil, err + } + + if rr.VCS == "mod" { + // Fetch module from proxy with base URL rr.Repo. + return newProxyRepo(rr.Repo, path) + } + + code, err := lookupCodeRepo(rr) + if err != nil { + return nil, err + } + return newCodeRepo(code, rr.Root, path) +} + +func lookupCodeRepo(rr *get.RepoRoot) (codehost.Repo, error) { + code, err := codehost.NewRepo(rr.VCS, rr.Repo) + if err != nil { + if _, ok := err.(*codehost.VCSError); ok { + return nil, err + } + return nil, fmt.Errorf("lookup %s: %v", rr.Root, err) + } + 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.Secure + if get.Insecure { + security = web.Insecure + } + rr, err := get.RepoRootForImportPath(path, get.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, "") + 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. +type loggingRepo struct { + r Repo +} + +func newLoggingRepo(r Repo) *loggingRepo { + return &loggingRepo{r} +} + +// logCall prints a log message using format and args and then +// also returns a function that will print the same message again, +// along with the elapsed time. +// Typical usage is: +// +// defer logCall("hello %s", arg)() +// +// Note the final (). +func logCall(format string, args ...interface{}) func() { + start := time.Now() + fmt.Fprintf(os.Stderr, "+++ %s\n", fmt.Sprintf(format, args...)) + return func() { + fmt.Fprintf(os.Stderr, "%.3fs %s\n", time.Since(start).Seconds(), fmt.Sprintf(format, args...)) + } +} + +func (l *loggingRepo) ModulePath() string { + return l.r.ModulePath() +} + +func (l *loggingRepo) Versions(prefix string) (tags []string, err error) { + defer logCall("Repo[%s]: Versions(%q)", l.r.ModulePath(), prefix)() + return l.r.Versions(prefix) +} + +func (l *loggingRepo) Stat(rev string) (*RevInfo, error) { + defer logCall("Repo[%s]: Stat(%q)", l.r.ModulePath(), rev)() + return l.r.Stat(rev) +} + +func (l *loggingRepo) Latest() (*RevInfo, error) { + defer logCall("Repo[%s]: Latest()", l.r.ModulePath())() + return l.r.Latest() +} + +func (l *loggingRepo) GoMod(version string) ([]byte, error) { + defer logCall("Repo[%s]: GoMod(%q)", l.r.ModulePath(), version)() + return l.r.GoMod(version) +} + +func (l *loggingRepo) Zip(version, tmpdir string) (string, error) { + defer logCall("Repo[%s]: Zip(%q, %q)", l.r.ModulePath(), version, tmpdir)() + return l.r.Zip(version, tmpdir) +} diff --git a/libgo/go/cmd/go/internal/modfetch/unzip.go b/libgo/go/cmd/go/internal/modfetch/unzip.go new file mode 100644 index 00000000000..a50431fd862 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/unzip.go @@ -0,0 +1,153 @@ +// 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 ( + "archive/zip" + "fmt" + "io" + "io/ioutil" + "os" + "path" + "path/filepath" + "sort" + "strings" + + "cmd/go/internal/modfetch/codehost" + "cmd/go/internal/module" + "cmd/go/internal/str" +) + +func Unzip(dir, zipfile, prefix string, maxSize int64) error { + if maxSize == 0 { + maxSize = codehost.MaxZipFile + } + + // Directory can exist, but must be empty. + // except maybe + files, _ := ioutil.ReadDir(dir) + if len(files) > 0 { + return fmt.Errorf("target directory %v exists and is not empty", dir) + } + if err := os.MkdirAll(dir, 0777); err != nil { + return err + } + + f, err := os.Open(zipfile) + if err != nil { + return err + } + defer f.Close() + info, err := f.Stat() + if err != nil { + return err + } + + z, err := zip.NewReader(f, info.Size()) + if err != nil { + return fmt.Errorf("unzip %v: %s", zipfile, err) + } + + foldPath := make(map[string]string) + var checkFold func(string) error + checkFold = func(name string) error { + fold := str.ToFold(name) + if foldPath[fold] == name { + return nil + } + dir := path.Dir(name) + if dir != "." { + if err := checkFold(dir); err != nil { + return err + } + } + if foldPath[fold] == "" { + foldPath[fold] = name + return nil + } + other := foldPath[fold] + return fmt.Errorf("unzip %v: case-insensitive file name collision: %q and %q", zipfile, other, name) + } + + // Check total size, valid file names. + var size int64 + for _, zf := range z.File { + if !str.HasPathPrefix(zf.Name, prefix) { + return fmt.Errorf("unzip %v: unexpected file name %s", zipfile, zf.Name) + } + if zf.Name == prefix || strings.HasSuffix(zf.Name, "/") { + continue + } + name := zf.Name[len(prefix)+1:] + if err := module.CheckFilePath(name); err != nil { + return fmt.Errorf("unzip %v: %v", zipfile, err) + } + if err := checkFold(name); err != nil { + return err + } + if path.Clean(zf.Name) != zf.Name || strings.HasPrefix(zf.Name[len(prefix)+1:], "/") { + return fmt.Errorf("unzip %v: invalid file name %s", zipfile, zf.Name) + } + s := int64(zf.UncompressedSize64) + if s < 0 || maxSize-size < s { + return fmt.Errorf("unzip %v: content too large", zipfile) + } + size += s + } + + // Unzip, enforcing sizes checked earlier. + dirs := map[string]bool{dir: true} + for _, zf := range z.File { + if zf.Name == prefix || strings.HasSuffix(zf.Name, "/") { + continue + } + name := zf.Name[len(prefix):] + dst := filepath.Join(dir, name) + parent := filepath.Dir(dst) + for parent != dir { + dirs[parent] = true + parent = filepath.Dir(parent) + } + if err := os.MkdirAll(filepath.Dir(dst), 0777); err != nil { + return err + } + w, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0444) + if err != nil { + return fmt.Errorf("unzip %v: %v", zipfile, err) + } + r, err := zf.Open() + if err != nil { + w.Close() + return fmt.Errorf("unzip %v: %v", zipfile, err) + } + lr := &io.LimitedReader{R: r, N: int64(zf.UncompressedSize64) + 1} + _, err = io.Copy(w, lr) + r.Close() + if err != nil { + w.Close() + return fmt.Errorf("unzip %v: %v", zipfile, err) + } + if err := w.Close(); err != nil { + return fmt.Errorf("unzip %v: %v", zipfile, err) + } + if lr.N <= 0 { + return fmt.Errorf("unzip %v: content too large", zipfile) + } + } + + // Mark directories unwritable, best effort. + var dirlist []string + for dir := range dirs { + dirlist = append(dirlist, dir) + } + sort.Strings(dirlist) + + // Run over list backward to chmod children before parents. + for i := len(dirlist) - 1; i >= 0; i-- { + os.Chmod(dirlist[i], 0555) + } + + return nil +} diff --git a/libgo/go/cmd/go/internal/modfetch/web.go b/libgo/go/cmd/go/internal/modfetch/web.go new file mode 100644 index 00000000000..b327bf293d1 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfetch/web.go @@ -0,0 +1,31 @@ +// 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 !cmd_go_bootstrap + +package modfetch + +import ( + "io" + + web "cmd/go/internal/web2" +) + +// webGetGoGet fetches a go-get=1 URL and returns the body in *body. +// It allows non-200 responses, as usual for these URLs. +func webGetGoGet(url string, body *io.ReadCloser) error { + return web.Get(url, web.Non200OK(), web.Body(body)) +} + +// webGetBytes returns the body returned by an HTTP GET, as a []byte. +// It insists on a 200 response. +func webGetBytes(url string, body *[]byte) error { + return web.Get(url, web.ReadAllBody(body)) +} + +// webGetBody returns the body returned by an HTTP GET, as a io.ReadCloser. +// It insists on a 200 response. +func webGetBody(url string, body *io.ReadCloser) error { + return web.Get(url, web.Body(body)) +} diff --git a/libgo/go/cmd/go/internal/modfile/gopkgin.go b/libgo/go/cmd/go/internal/modfile/gopkgin.go new file mode 100644 index 00000000000..c94b3848a0e --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/gopkgin.go @@ -0,0 +1,47 @@ +// 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: Figure out what gopkg.in should do. + +package modfile + +import "strings" + +// ParseGopkgIn splits gopkg.in import paths into their constituent parts +func ParseGopkgIn(path string) (root, repo, major, subdir string, ok bool) { + if !strings.HasPrefix(path, "gopkg.in/") { + return + } + f := strings.Split(path, "/") + if len(f) >= 2 { + if elem, v, ok := dotV(f[1]); ok { + root = strings.Join(f[:2], "/") + repo = "github.com/go-" + elem + "/" + elem + major = v + subdir = strings.Join(f[2:], "/") + return root, repo, major, subdir, true + } + } + if len(f) >= 3 { + if elem, v, ok := dotV(f[2]); ok { + root = strings.Join(f[:3], "/") + repo = "github.com/" + f[1] + "/" + elem + major = v + subdir = strings.Join(f[3:], "/") + return root, repo, major, subdir, true + } + } + return +} + +func dotV(name string) (elem, v string, ok bool) { + i := len(name) - 1 + for i >= 0 && '0' <= name[i] && name[i] <= '9' { + i-- + } + if i <= 2 || i+1 >= len(name) || name[i-1] != '.' || name[i] != 'v' || name[i+1] == '0' && len(name) != i+2 { + return "", "", false + } + return name[:i-1], name[i:], true +} diff --git a/libgo/go/cmd/go/internal/modfile/print.go b/libgo/go/cmd/go/internal/modfile/print.go new file mode 100644 index 00000000000..cefc43b141c --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/print.go @@ -0,0 +1,164 @@ +// 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. + +// Module file printer. + +package modfile + +import ( + "bytes" + "fmt" + "strings" +) + +func Format(f *FileSyntax) []byte { + pr := &printer{} + pr.file(f) + return pr.Bytes() +} + +// A printer collects the state during printing of a file or expression. +type printer struct { + bytes.Buffer // output buffer + comment []Comment // pending end-of-line comments + margin int // left margin (indent), a number of tabs +} + +// printf prints to the buffer. +func (p *printer) printf(format string, args ...interface{}) { + fmt.Fprintf(p, format, args...) +} + +// indent returns the position on the current line, in bytes, 0-indexed. +func (p *printer) indent() int { + b := p.Bytes() + n := 0 + for n < len(b) && b[len(b)-1-n] != '\n' { + n++ + } + return n +} + +// newline ends the current line, flushing end-of-line comments. +func (p *printer) newline() { + if len(p.comment) > 0 { + p.printf(" ") + for i, com := range p.comment { + if i > 0 { + p.trim() + p.printf("\n") + for i := 0; i < p.margin; i++ { + p.printf("\t") + } + } + p.printf("%s", strings.TrimSpace(com.Token)) + } + p.comment = p.comment[:0] + } + + p.trim() + p.printf("\n") + for i := 0; i < p.margin; i++ { + p.printf("\t") + } +} + +// trim removes trailing spaces and tabs from the current line. +func (p *printer) trim() { + // Remove trailing spaces and tabs from line we're about to end. + b := p.Bytes() + n := len(b) + for n > 0 && (b[n-1] == '\t' || b[n-1] == ' ') { + n-- + } + p.Truncate(n) +} + +// file formats the given file into the print buffer. +func (p *printer) file(f *FileSyntax) { + for _, com := range f.Before { + p.printf("%s", strings.TrimSpace(com.Token)) + p.newline() + } + + for i, stmt := range f.Stmt { + switch x := stmt.(type) { + case *CommentBlock: + // comments already handled + p.expr(x) + + default: + p.expr(x) + p.newline() + } + + for _, com := range stmt.Comment().After { + p.printf("%s", strings.TrimSpace(com.Token)) + p.newline() + } + + if i+1 < len(f.Stmt) { + p.newline() + } + } +} + +func (p *printer) expr(x Expr) { + // Emit line-comments preceding this expression. + if before := x.Comment().Before; len(before) > 0 { + // Want to print a line comment. + // Line comments must be at the current margin. + p.trim() + if p.indent() > 0 { + // There's other text on the line. Start a new line. + p.printf("\n") + } + // Re-indent to margin. + for i := 0; i < p.margin; i++ { + p.printf("\t") + } + for _, com := range before { + p.printf("%s", strings.TrimSpace(com.Token)) + p.newline() + } + } + + switch x := x.(type) { + default: + panic(fmt.Errorf("printer: unexpected type %T", x)) + + case *CommentBlock: + // done + + case *LParen: + p.printf("(") + case *RParen: + p.printf(")") + + case *Line: + sep := "" + for _, tok := range x.Token { + p.printf("%s%s", sep, tok) + sep = " " + } + + case *LineBlock: + for _, tok := range x.Token { + p.printf("%s ", tok) + } + p.expr(&x.LParen) + p.margin++ + for _, l := range x.Line { + p.newline() + p.expr(l) + } + p.margin-- + p.newline() + p.expr(&x.RParen) + } + + // Queue end-of-line comments for printing when we + // reach the end of the line. + p.comment = append(p.comment, x.Comment().Suffix...) +} diff --git a/libgo/go/cmd/go/internal/modfile/read.go b/libgo/go/cmd/go/internal/modfile/read.go new file mode 100644 index 00000000000..1d81ff1ab7a --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/read.go @@ -0,0 +1,869 @@ +// 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. + +// Module file parser. +// This is a simplified copy of Google's buildifier parser. + +package modfile + +import ( + "bytes" + "fmt" + "os" + "strconv" + "strings" + "unicode" + "unicode/utf8" +) + +// A Position describes the position between two bytes of input. +type Position struct { + Line int // line in input (starting at 1) + LineRune int // rune in line (starting at 1) + Byte int // byte in input (starting at 0) +} + +// add returns the position at the end of s, assuming it starts at p. +func (p Position) add(s string) Position { + p.Byte += len(s) + if n := strings.Count(s, "\n"); n > 0 { + p.Line += n + s = s[strings.LastIndex(s, "\n")+1:] + p.LineRune = 1 + } + p.LineRune += utf8.RuneCountInString(s) + return p +} + +// An Expr represents an input element. +type Expr interface { + // Span returns the start and end position of the expression, + // excluding leading or trailing comments. + Span() (start, end Position) + + // Comment returns the comments attached to the expression. + // This method would normally be named 'Comments' but that + // would interfere with embedding a type of the same name. + Comment() *Comments +} + +// A Comment represents a single // comment. +type Comment struct { + Start Position + Token string // without trailing newline + Suffix bool // an end of line (not whole line) comment +} + +// Comments collects the comments associated with an expression. +type Comments struct { + Before []Comment // whole-line comments before this expression + Suffix []Comment // end-of-line comments after this expression + + // For top-level expressions only, After lists whole-line + // comments following the expression. + After []Comment +} + +// Comment returns the receiver. This isn't useful by itself, but +// a Comments struct is embedded into all the expression +// implementation types, and this gives each of those a Comment +// method to satisfy the Expr interface. +func (c *Comments) Comment() *Comments { + return c +} + +// A FileSyntax represents an entire go.mod file. +type FileSyntax struct { + Name string // file path + Comments + Stmt []Expr +} + +func (x *FileSyntax) Span() (start, end Position) { + if len(x.Stmt) == 0 { + return + } + start, _ = x.Stmt[0].Span() + _, end = x.Stmt[len(x.Stmt)-1].Span() + return start, end +} + +func (x *FileSyntax) addLine(hint Expr, tokens ...string) *Line { + if hint == nil { + // If no hint given, add to the last statement of the given type. + Loop: + for i := len(x.Stmt) - 1; i >= 0; i-- { + stmt := x.Stmt[i] + switch stmt := stmt.(type) { + case *Line: + if stmt.Token != nil && stmt.Token[0] == tokens[0] { + hint = stmt + break Loop + } + case *LineBlock: + if stmt.Token[0] == tokens[0] { + hint = stmt + break Loop + } + } + } + } + + if hint != nil { + for i, stmt := range x.Stmt { + switch stmt := stmt.(type) { + case *Line: + if stmt == hint { + // Convert line to line block. + stmt.InBlock = true + block := &LineBlock{Token: stmt.Token[:1], Line: []*Line{stmt}} + stmt.Token = stmt.Token[1:] + x.Stmt[i] = block + new := &Line{Token: tokens[1:], InBlock: true} + block.Line = append(block.Line, new) + return new + } + case *LineBlock: + if stmt == hint { + new := &Line{Token: tokens[1:], InBlock: true} + stmt.Line = append(stmt.Line, new) + return new + } + for j, line := range stmt.Line { + if line == hint { + // Add new line after hint. + stmt.Line = append(stmt.Line, nil) + copy(stmt.Line[j+2:], stmt.Line[j+1:]) + new := &Line{Token: tokens[1:], InBlock: true} + stmt.Line[j+1] = new + return new + } + } + } + } + } + + new := &Line{Token: tokens} + x.Stmt = append(x.Stmt, new) + return new +} + +func (x *FileSyntax) updateLine(line *Line, tokens ...string) { + if line.InBlock { + tokens = tokens[1:] + } + line.Token = tokens +} + +func (x *FileSyntax) removeLine(line *Line) { + line.Token = nil +} + +// Cleanup cleans up the file syntax x after any edit operations. +// To avoid quadratic behavior, removeLine 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. +func (x *FileSyntax) Cleanup() { + w := 0 + for _, stmt := range x.Stmt { + switch stmt := stmt.(type) { + case *Line: + if stmt.Token == nil { + continue + } + case *LineBlock: + ww := 0 + for _, line := range stmt.Line { + if line.Token != nil { + stmt.Line[ww] = line + ww++ + } + } + if ww == 0 { + continue + } + if ww == 1 { + // Collapse block into single line. + line := &Line{ + Comments: Comments{ + Before: commentsAdd(stmt.Before, stmt.Line[0].Before), + Suffix: commentsAdd(stmt.Line[0].Suffix, stmt.Suffix), + After: commentsAdd(stmt.Line[0].After, stmt.After), + }, + Token: stringsAdd(stmt.Token, stmt.Line[0].Token), + } + x.Stmt[w] = line + w++ + continue + } + stmt.Line = stmt.Line[:ww] + } + x.Stmt[w] = stmt + w++ + } + x.Stmt = x.Stmt[:w] +} + +func commentsAdd(x, y []Comment) []Comment { + return append(x[:len(x):len(x)], y...) +} + +func stringsAdd(x, y []string) []string { + return append(x[:len(x):len(x)], y...) +} + +// A CommentBlock represents a top-level block of comments separate +// from any rule. +type CommentBlock struct { + Comments + Start Position +} + +func (x *CommentBlock) Span() (start, end Position) { + return x.Start, x.Start +} + +// A Line is a single line of tokens. +type Line struct { + Comments + Start Position + Token []string + InBlock bool + End Position +} + +func (x *Line) Span() (start, end Position) { + return x.Start, x.End +} + +// A LineBlock is a factored block of lines, like +// +// require ( +// "x" +// "y" +// ) +// +type LineBlock struct { + Comments + Start Position + LParen LParen + Token []string + Line []*Line + RParen RParen +} + +func (x *LineBlock) Span() (start, end Position) { + return x.Start, x.RParen.Pos.add(")") +} + +// An LParen represents the beginning of a parenthesized line block. +// It is a place to store suffix comments. +type LParen struct { + Comments + Pos Position +} + +func (x *LParen) Span() (start, end Position) { + return x.Pos, x.Pos.add(")") +} + +// An RParen represents the end of a parenthesized line block. +// It is a place to store whole-line (before) comments. +type RParen struct { + Comments + Pos Position +} + +func (x *RParen) Span() (start, end Position) { + return x.Pos, x.Pos.add(")") +} + +// An input represents a single input file being parsed. +type input struct { + // Lexing state. + filename string // name of input file, for errors + complete []byte // entire input + remaining []byte // remaining input + token []byte // token being scanned + lastToken string // most recently returned token, for error messages + pos Position // current input position + comments []Comment // accumulated comments + endRule int // position of end of current rule + + // Parser state. + file *FileSyntax // returned top-level syntax tree + parseError error // error encountered during parsing + + // Comment assignment state. + pre []Expr // all expressions, in preorder traversal + post []Expr // all expressions, in postorder traversal +} + +func newInput(filename string, data []byte) *input { + return &input{ + filename: filename, + complete: data, + remaining: data, + pos: Position{Line: 1, LineRune: 1, Byte: 0}, + } +} + +// parse parses the input file. +func parse(file string, data []byte) (f *FileSyntax, err error) { + in := newInput(file, data) + // The parser panics for both routine errors like syntax errors + // and for programmer bugs like array index errors. + // Turn both into error returns. Catching bug panics is + // especially important when processing many files. + defer func() { + if e := recover(); e != nil { + if e == in.parseError { + err = in.parseError + } else { + err = fmt.Errorf("%s:%d:%d: internal error: %v", in.filename, in.pos.Line, in.pos.LineRune, e) + } + } + }() + + // Invoke the parser. + in.parseFile() + if in.parseError != nil { + return nil, in.parseError + } + in.file.Name = in.filename + + // Assign comments to nearby syntax. + in.assignComments() + + return in.file, nil +} + +// Error is called to report an error. +// The reason s is often "syntax error". +// Error does not return: it panics. +func (in *input) Error(s string) { + if s == "syntax error" && in.lastToken != "" { + s += " near " + in.lastToken + } + in.parseError = fmt.Errorf("%s:%d:%d: %v", in.filename, in.pos.Line, in.pos.LineRune, s) + panic(in.parseError) +} + +// eof reports whether the input has reached end of file. +func (in *input) eof() bool { + return len(in.remaining) == 0 +} + +// peekRune returns the next rune in the input without consuming it. +func (in *input) peekRune() int { + if len(in.remaining) == 0 { + return 0 + } + r, _ := utf8.DecodeRune(in.remaining) + return int(r) +} + +// peekPrefix reports whether the remaining input begins with the given prefix. +func (in *input) peekPrefix(prefix string) bool { + // This is like bytes.HasPrefix(in.remaining, []byte(prefix)) + // but without the allocation of the []byte copy of prefix. + for i := 0; i < len(prefix); i++ { + if i >= len(in.remaining) || in.remaining[i] != prefix[i] { + return false + } + } + return true +} + +// readRune consumes and returns the next rune in the input. +func (in *input) readRune() int { + if len(in.remaining) == 0 { + in.Error("internal lexer error: readRune at EOF") + } + r, size := utf8.DecodeRune(in.remaining) + in.remaining = in.remaining[size:] + if r == '\n' { + in.pos.Line++ + in.pos.LineRune = 1 + } else { + in.pos.LineRune++ + } + in.pos.Byte += size + return int(r) +} + +type symType struct { + pos Position + endPos Position + text string +} + +// startToken marks the beginning of the next input token. +// It must be followed by a call to endToken, once the token has +// been consumed using readRune. +func (in *input) startToken(sym *symType) { + in.token = in.remaining + sym.text = "" + sym.pos = in.pos +} + +// endToken marks the end of an input token. +// It records the actual token string in sym.text if the caller +// has not done that already. +func (in *input) endToken(sym *symType) { + if sym.text == "" { + tok := string(in.token[:len(in.token)-len(in.remaining)]) + sym.text = tok + in.lastToken = sym.text + } + sym.endPos = in.pos +} + +// lex is called from the parser to obtain the next input token. +// It returns the token value (either a rune like '+' or a symbolic token _FOR) +// and sets val to the data associated with the token. +// For all our input tokens, the associated data is +// val.Pos (the position where the token begins) +// and val.Token (the input string corresponding to the token). +func (in *input) lex(sym *symType) int { + // Skip past spaces, stopping at non-space or EOF. + countNL := 0 // number of newlines we've skipped past + for !in.eof() { + // Skip over spaces. Count newlines so we can give the parser + // information about where top-level blank lines are, + // for top-level comment assignment. + c := in.peekRune() + if c == ' ' || c == '\t' || c == '\r' { + in.readRune() + continue + } + + // Comment runs to end of line. + if in.peekPrefix("//") { + in.startToken(sym) + + // Is this comment the only thing on its line? + // Find the last \n before this // and see if it's all + // spaces from there to here. + i := bytes.LastIndex(in.complete[:in.pos.Byte], []byte("\n")) + suffix := len(bytes.TrimSpace(in.complete[i+1:in.pos.Byte])) > 0 + in.readRune() + in.readRune() + + // Consume comment. + for len(in.remaining) > 0 && in.readRune() != '\n' { + } + in.endToken(sym) + + sym.text = strings.TrimRight(sym.text, "\n") + in.lastToken = "comment" + + // If we are at top level (not in a statement), hand the comment to + // the parser as a _COMMENT token. The grammar is written + // to handle top-level comments itself. + if !suffix { + // Not in a statement. Tell parser about top-level comment. + return _COMMENT + } + + // Otherwise, save comment for later attachment to syntax tree. + if countNL > 1 { + in.comments = append(in.comments, Comment{sym.pos, "", false}) + } + in.comments = append(in.comments, Comment{sym.pos, sym.text, suffix}) + countNL = 1 + return _EOL + } + + if in.peekPrefix("/*") { + in.Error(fmt.Sprintf("mod files must use // comments (not /* */ comments)")) + } + + // Found non-space non-comment. + break + } + + // Found the beginning of the next token. + in.startToken(sym) + defer in.endToken(sym) + + // End of file. + if in.eof() { + in.lastToken = "EOF" + return _EOF + } + + // Punctuation tokens. + switch c := in.peekRune(); c { + case '\n': + in.readRune() + return c + + case '(': + in.readRune() + return c + + case ')': + in.readRune() + return c + + case '"', '`': // quoted string + quote := c + in.readRune() + for { + if in.eof() { + in.pos = sym.pos + in.Error("unexpected EOF in string") + } + if in.peekRune() == '\n' { + in.Error("unexpected newline in string") + } + c := in.readRune() + if c == quote { + break + } + if c == '\\' && quote != '`' { + if in.eof() { + in.pos = sym.pos + in.Error("unexpected EOF in string") + } + in.readRune() + } + } + in.endToken(sym) + return _STRING + } + + // Checked all punctuation. Must be identifier token. + if c := in.peekRune(); !isIdent(c) { + in.Error(fmt.Sprintf("unexpected input character %#q", c)) + } + + // Scan over identifier. + for isIdent(in.peekRune()) { + if in.peekPrefix("//") { + break + } + if in.peekPrefix("/*") { + in.Error(fmt.Sprintf("mod files must use // comments (not /* */ comments)")) + } + in.readRune() + } + return _IDENT +} + +// isIdent reports whether c is an identifier rune. +// We treat nearly all runes as identifier runes. +func isIdent(c int) bool { + return c != 0 && !unicode.IsSpace(rune(c)) +} + +// Comment assignment. +// We build two lists of all subexpressions, preorder and postorder. +// The preorder list is ordered by start location, with outer expressions first. +// The postorder list is ordered by end location, with outer expressions last. +// We use the preorder list to assign each whole-line comment to the syntax +// immediately following it, and we use the postorder list to assign each +// end-of-line comment to the syntax immediately preceding it. + +// order walks the expression adding it and its subexpressions to the +// preorder and postorder lists. +func (in *input) order(x Expr) { + if x != nil { + in.pre = append(in.pre, x) + } + switch x := x.(type) { + default: + panic(fmt.Errorf("order: unexpected type %T", x)) + case nil: + // nothing + case *LParen, *RParen: + // nothing + case *CommentBlock: + // nothing + case *Line: + // nothing + case *FileSyntax: + for _, stmt := range x.Stmt { + in.order(stmt) + } + case *LineBlock: + in.order(&x.LParen) + for _, l := range x.Line { + in.order(l) + } + in.order(&x.RParen) + } + if x != nil { + in.post = append(in.post, x) + } +} + +// assignComments attaches comments to nearby syntax. +func (in *input) assignComments() { + const debug = false + + // Generate preorder and postorder lists. + in.order(in.file) + + // Split into whole-line comments and suffix comments. + var line, suffix []Comment + for _, com := range in.comments { + if com.Suffix { + suffix = append(suffix, com) + } else { + line = append(line, com) + } + } + + if debug { + for _, c := range line { + fmt.Fprintf(os.Stderr, "LINE %q :%d:%d #%d\n", c.Token, c.Start.Line, c.Start.LineRune, c.Start.Byte) + } + } + + // Assign line comments to syntax immediately following. + for _, x := range in.pre { + start, _ := x.Span() + if debug { + fmt.Printf("pre %T :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte) + } + xcom := x.Comment() + for len(line) > 0 && start.Byte >= line[0].Start.Byte { + if debug { + fmt.Fprintf(os.Stderr, "ASSIGN LINE %q #%d\n", line[0].Token, line[0].Start.Byte) + } + xcom.Before = append(xcom.Before, line[0]) + line = line[1:] + } + } + + // Remaining line comments go at end of file. + in.file.After = append(in.file.After, line...) + + if debug { + for _, c := range suffix { + fmt.Fprintf(os.Stderr, "SUFFIX %q :%d:%d #%d\n", c.Token, c.Start.Line, c.Start.LineRune, c.Start.Byte) + } + } + + // Assign suffix comments to syntax immediately before. + for i := len(in.post) - 1; i >= 0; i-- { + x := in.post[i] + + start, end := x.Span() + if debug { + fmt.Printf("post %T :%d:%d #%d :%d:%d #%d\n", x, start.Line, start.LineRune, start.Byte, end.Line, end.LineRune, end.Byte) + } + + // Do not assign suffix comments to end of line block or whole file. + // Instead assign them to the last element inside. + switch x.(type) { + case *FileSyntax: + continue + } + + // Do not assign suffix comments to something that starts + // on an earlier line, so that in + // + // x ( y + // z ) // comment + // + // we assign the comment to z and not to x ( ... ). + if start.Line != end.Line { + continue + } + xcom := x.Comment() + for len(suffix) > 0 && end.Byte <= suffix[len(suffix)-1].Start.Byte { + if debug { + fmt.Fprintf(os.Stderr, "ASSIGN SUFFIX %q #%d\n", suffix[len(suffix)-1].Token, suffix[len(suffix)-1].Start.Byte) + } + xcom.Suffix = append(xcom.Suffix, suffix[len(suffix)-1]) + suffix = suffix[:len(suffix)-1] + } + } + + // We assigned suffix comments in reverse. + // If multiple suffix comments were appended to the same + // expression node, they are now in reverse. Fix that. + for _, x := range in.post { + reverseComments(x.Comment().Suffix) + } + + // Remaining suffix comments go at beginning of file. + in.file.Before = append(in.file.Before, suffix...) +} + +// reverseComments reverses the []Comment list. +func reverseComments(list []Comment) { + for i, j := 0, len(list)-1; i < j; i, j = i+1, j-1 { + list[i], list[j] = list[j], list[i] + } +} + +func (in *input) parseFile() { + in.file = new(FileSyntax) + var sym symType + var cb *CommentBlock + for { + tok := in.lex(&sym) + switch tok { + case '\n': + if cb != nil { + in.file.Stmt = append(in.file.Stmt, cb) + cb = nil + } + case _COMMENT: + if cb == nil { + cb = &CommentBlock{Start: sym.pos} + } + com := cb.Comment() + com.Before = append(com.Before, Comment{Start: sym.pos, Token: sym.text}) + case _EOF: + if cb != nil { + in.file.Stmt = append(in.file.Stmt, cb) + } + return + default: + in.parseStmt(&sym) + if cb != nil { + in.file.Stmt[len(in.file.Stmt)-1].Comment().Before = cb.Before + cb = nil + } + } + } +} + +func (in *input) parseStmt(sym *symType) { + start := sym.pos + end := sym.endPos + token := []string{sym.text} + for { + tok := in.lex(sym) + switch tok { + case '\n', _EOF, _EOL: + in.file.Stmt = append(in.file.Stmt, &Line{ + Start: start, + Token: token, + End: end, + }) + return + case '(': + in.file.Stmt = append(in.file.Stmt, in.parseLineBlock(start, token, sym)) + return + default: + token = append(token, sym.text) + end = sym.endPos + } + } +} + +func (in *input) parseLineBlock(start Position, token []string, sym *symType) *LineBlock { + x := &LineBlock{ + Start: start, + Token: token, + LParen: LParen{Pos: sym.pos}, + } + var comments []Comment + for { + tok := in.lex(sym) + switch tok { + case _EOL: + // ignore + case '\n': + if len(comments) == 0 && len(x.Line) > 0 || len(comments) > 0 && comments[len(comments)-1].Token != "" { + comments = append(comments, Comment{}) + } + case _COMMENT: + comments = append(comments, Comment{Start: sym.pos, Token: sym.text}) + case _EOF: + in.Error(fmt.Sprintf("syntax error (unterminated block started at %s:%d:%d)", in.filename, x.Start.Line, x.Start.LineRune)) + case ')': + x.RParen.Before = comments + x.RParen.Pos = sym.pos + tok = in.lex(sym) + if tok != '\n' && tok != _EOF && tok != _EOL { + in.Error("syntax error (expected newline after closing paren)") + } + return x + default: + l := in.parseLine(sym) + x.Line = append(x.Line, l) + l.Comment().Before = comments + comments = nil + } + } +} + +func (in *input) parseLine(sym *symType) *Line { + start := sym.pos + end := sym.endPos + token := []string{sym.text} + for { + tok := in.lex(sym) + switch tok { + case '\n', _EOF, _EOL: + return &Line{ + Start: start, + Token: token, + End: end, + InBlock: true, + } + default: + token = append(token, sym.text) + end = sym.endPos + } + } +} + +const ( + _EOF = -(1 + iota) + _EOL + _IDENT + _STRING + _COMMENT +) + +var ( + slashSlash = []byte("//") + moduleStr = []byte("module") +) + +// ModulePath returns the module path from the gomod file text. +// If it cannot find a module path, it returns an empty string. +// It is tolerant of unrelated problems in the go.mod file. +func ModulePath(mod []byte) string { + for len(mod) > 0 { + line := mod + mod = nil + if i := bytes.IndexByte(line, '\n'); i >= 0 { + line, mod = line[:i], line[i+1:] + } + if i := bytes.Index(line, slashSlash); i >= 0 { + line = line[:i] + } + line = bytes.TrimSpace(line) + if !bytes.HasPrefix(line, moduleStr) { + continue + } + line = line[len(moduleStr):] + n := len(line) + line = bytes.TrimSpace(line) + if len(line) == n || len(line) == 0 { + continue + } + + if line[0] == '"' || line[0] == '`' { + p, err := strconv.Unquote(string(line)) + if err != nil { + return "" // malformed quoted string or multiline module path + } + return p + } + + return string(line) + } + return "" // missing module path +} diff --git a/libgo/go/cmd/go/internal/modfile/read_test.go b/libgo/go/cmd/go/internal/modfile/read_test.go new file mode 100644 index 00000000000..8cb1a3908c5 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/read_test.go @@ -0,0 +1,365 @@ +// 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 modfile + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "reflect" + "strings" + "testing" +) + +// exists reports whether the named file exists. +func exists(name string) bool { + _, err := os.Stat(name) + return err == nil +} + +// Test that reading and then writing the golden files +// does not change their output. +func TestPrintGolden(t *testing.T) { + outs, err := filepath.Glob("testdata/*.golden") + if err != nil { + t.Fatal(err) + } + for _, out := range outs { + testPrint(t, out, out) + } +} + +// testPrint is a helper for testing the printer. +// It reads the file named in, reformats it, and compares +// the result to the file named out. +func testPrint(t *testing.T, in, out string) { + data, err := ioutil.ReadFile(in) + if err != nil { + t.Error(err) + return + } + + golden, err := ioutil.ReadFile(out) + if err != nil { + t.Error(err) + return + } + + base := "testdata/" + filepath.Base(in) + f, err := parse(in, data) + if err != nil { + t.Error(err) + return + } + + ndata := Format(f) + + if !bytes.Equal(ndata, golden) { + t.Errorf("formatted %s incorrectly: diff shows -golden, +ours", base) + tdiff(t, string(golden), string(ndata)) + return + } +} + +func TestParseLax(t *testing.T) { + badFile := []byte(`module m + surprise attack + x y ( + z + ) + exclude v1.2.3 + replace <-!!! + `) + _, err := ParseLax("file", badFile, nil) + if err != nil { + t.Fatalf("ParseLax did not ignore irrelevant errors: %v", err) + } +} + +// Test that when files in the testdata directory are parsed +// and printed and parsed again, we get the same parse tree +// both times. +func TestPrintParse(t *testing.T) { + outs, err := filepath.Glob("testdata/*") + if err != nil { + t.Fatal(err) + } + for _, out := range outs { + data, err := ioutil.ReadFile(out) + if err != nil { + t.Error(err) + continue + } + + base := "testdata/" + filepath.Base(out) + f, err := parse(base, data) + if err != nil { + t.Errorf("parsing original: %v", err) + continue + } + + ndata := Format(f) + f2, err := parse(base, ndata) + if err != nil { + t.Errorf("parsing reformatted: %v", err) + continue + } + + eq := eqchecker{file: base} + if err := eq.check(f, f2); err != nil { + t.Errorf("not equal (parse/Format/parse): %v", err) + } + + pf1, err := Parse(base, data, nil) + if err != nil { + switch base { + case "testdata/replace2.in", "testdata/gopkg.in.golden": + t.Errorf("should parse %v: %v", base, err) + } + } + if err == nil { + pf2, err := Parse(base, ndata, nil) + if err != nil { + t.Errorf("Parsing reformatted: %v", err) + continue + } + eq := eqchecker{file: base} + if err := eq.check(pf1, pf2); err != nil { + t.Errorf("not equal (parse/Format/Parse): %v", err) + } + + ndata2, err := pf1.Format() + if err != nil { + t.Errorf("reformat: %v", err) + } + pf3, err := Parse(base, ndata2, nil) + if err != nil { + t.Errorf("Parsing reformatted2: %v", err) + continue + } + eq = eqchecker{file: base} + if err := eq.check(pf1, pf3); err != nil { + t.Errorf("not equal (Parse/Format/Parse): %v", err) + } + ndata = ndata2 + } + + if strings.HasSuffix(out, ".in") { + golden, err := ioutil.ReadFile(strings.TrimSuffix(out, ".in") + ".golden") + if err != nil { + t.Error(err) + continue + } + if !bytes.Equal(ndata, golden) { + t.Errorf("formatted %s incorrectly: diff shows -golden, +ours", base) + tdiff(t, string(golden), string(ndata)) + return + } + } + } +} + +// An eqchecker holds state for checking the equality of two parse trees. +type eqchecker struct { + file string + pos Position +} + +// errorf returns an error described by the printf-style format and arguments, +// inserting the current file position before the error text. +func (eq *eqchecker) errorf(format string, args ...interface{}) error { + return fmt.Errorf("%s:%d: %s", eq.file, eq.pos.Line, + fmt.Sprintf(format, args...)) +} + +// check checks that v and w represent the same parse tree. +// If not, it returns an error describing the first difference. +func (eq *eqchecker) check(v, w interface{}) error { + return eq.checkValue(reflect.ValueOf(v), reflect.ValueOf(w)) +} + +var ( + posType = reflect.TypeOf(Position{}) + commentsType = reflect.TypeOf(Comments{}) +) + +// checkValue checks that v and w represent the same parse tree. +// If not, it returns an error describing the first difference. +func (eq *eqchecker) checkValue(v, w reflect.Value) error { + // inner returns the innermost expression for v. + // if v is a non-nil interface value, it returns the concrete + // value in the interface. + inner := func(v reflect.Value) reflect.Value { + for { + if v.Kind() == reflect.Interface && !v.IsNil() { + v = v.Elem() + continue + } + break + } + return v + } + + v = inner(v) + w = inner(w) + if v.Kind() == reflect.Invalid && w.Kind() == reflect.Invalid { + return nil + } + if v.Kind() == reflect.Invalid { + return eq.errorf("nil interface became %s", w.Type()) + } + if w.Kind() == reflect.Invalid { + return eq.errorf("%s became nil interface", v.Type()) + } + + if v.Type() != w.Type() { + return eq.errorf("%s became %s", v.Type(), w.Type()) + } + + if p, ok := v.Interface().(Expr); ok { + eq.pos, _ = p.Span() + } + + switch v.Kind() { + default: + return eq.errorf("unexpected type %s", v.Type()) + + case reflect.Bool, reflect.Int, reflect.String: + vi := v.Interface() + wi := w.Interface() + if vi != wi { + return eq.errorf("%v became %v", vi, wi) + } + + case reflect.Slice: + vl := v.Len() + wl := w.Len() + for i := 0; i < vl || i < wl; i++ { + if i >= vl { + return eq.errorf("unexpected %s", w.Index(i).Type()) + } + if i >= wl { + return eq.errorf("missing %s", v.Index(i).Type()) + } + if err := eq.checkValue(v.Index(i), w.Index(i)); err != nil { + return err + } + } + + case reflect.Struct: + // Fields in struct must match. + t := v.Type() + n := t.NumField() + for i := 0; i < n; i++ { + tf := t.Field(i) + switch { + default: + if err := eq.checkValue(v.Field(i), w.Field(i)); err != nil { + return err + } + + case tf.Type == posType: // ignore positions + case tf.Type == commentsType: // ignore comment assignment + } + } + + case reflect.Ptr, reflect.Interface: + if v.IsNil() != w.IsNil() { + if v.IsNil() { + return eq.errorf("unexpected %s", w.Elem().Type()) + } + return eq.errorf("missing %s", v.Elem().Type()) + } + if err := eq.checkValue(v.Elem(), w.Elem()); err != nil { + return err + } + } + return nil +} + +// diff returns the output of running diff on b1 and b2. +func diff(b1, b2 []byte) (data []byte, err error) { + f1, err := ioutil.TempFile("", "testdiff") + if err != nil { + return nil, err + } + defer os.Remove(f1.Name()) + defer f1.Close() + + f2, err := ioutil.TempFile("", "testdiff") + if err != nil { + return nil, err + } + defer os.Remove(f2.Name()) + defer f2.Close() + + f1.Write(b1) + f2.Write(b2) + + data, err = exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput() + if len(data) > 0 { + // diff exits with a non-zero status when the files don't match. + // Ignore that failure as long as we get output. + err = nil + } + return +} + +// tdiff logs the diff output to t.Error. +func tdiff(t *testing.T, a, b string) { + data, err := diff([]byte(a), []byte(b)) + if err != nil { + t.Error(err) + return + } + t.Error(string(data)) +} + +var modulePathTests = []struct { + input []byte + expected string +}{ + {input: []byte("module \"github.com/rsc/vgotest\""), expected: "github.com/rsc/vgotest"}, + {input: []byte("module github.com/rsc/vgotest"), expected: "github.com/rsc/vgotest"}, + {input: []byte("module \"github.com/rsc/vgotest\""), expected: "github.com/rsc/vgotest"}, + {input: []byte("module github.com/rsc/vgotest"), expected: "github.com/rsc/vgotest"}, + {input: []byte("module `github.com/rsc/vgotest`"), expected: "github.com/rsc/vgotest"}, + {input: []byte("module \"github.com/rsc/vgotest/v2\""), expected: "github.com/rsc/vgotest/v2"}, + {input: []byte("module github.com/rsc/vgotest/v2"), expected: "github.com/rsc/vgotest/v2"}, + {input: []byte("module \"gopkg.in/yaml.v2\""), expected: "gopkg.in/yaml.v2"}, + {input: []byte("module gopkg.in/yaml.v2"), expected: "gopkg.in/yaml.v2"}, + {input: []byte("module \"gopkg.in/check.v1\"\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module \"gopkg.in/check.v1\n\""), expected: ""}, + {input: []byte("module gopkg.in/check.v1\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module \"gopkg.in/check.v1\"\r\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module gopkg.in/check.v1\r\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module \"gopkg.in/check.v1\"\n\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module gopkg.in/check.v1\n\n"), expected: "gopkg.in/check.v1"}, + {input: []byte("module \n\"gopkg.in/check.v1\"\n\n"), expected: ""}, + {input: []byte("module \ngopkg.in/check.v1\n\n"), expected: ""}, + {input: []byte("module \"gopkg.in/check.v1\"asd"), expected: ""}, + {input: []byte("module \n\"gopkg.in/check.v1\"\n\n"), expected: ""}, + {input: []byte("module \ngopkg.in/check.v1\n\n"), expected: ""}, + {input: []byte("module \"gopkg.in/check.v1\"asd"), expected: ""}, + {input: []byte("module \nmodule a/b/c "), expected: "a/b/c"}, + {input: []byte("module \" \""), expected: " "}, + {input: []byte("module "), expected: ""}, + {input: []byte("module \" a/b/c \""), expected: " a/b/c "}, + {input: []byte("module \"github.com/rsc/vgotest1\" // with a comment"), expected: "github.com/rsc/vgotest1"}, +} + +func TestModulePath(t *testing.T) { + for _, test := range modulePathTests { + t.Run(string(test.input), func(t *testing.T) { + result := ModulePath(test.input) + if result != test.expected { + t.Fatalf("ModulePath(%q): %s, want %s", string(test.input), result, test.expected) + } + }) + } +} diff --git a/libgo/go/cmd/go/internal/modfile/rule.go b/libgo/go/cmd/go/internal/modfile/rule.go new file mode 100644 index 00000000000..e11f0a6e31e --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/rule.go @@ -0,0 +1,724 @@ +// 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 modfile + +import ( + "bytes" + "errors" + "fmt" + "path/filepath" + "regexp" + "sort" + "strconv" + "strings" + "unicode" + + "cmd/go/internal/module" + "cmd/go/internal/semver" +) + +// A File is the parsed, interpreted form of a go.mod file. +type File struct { + Module *Module + Go *Go + Require []*Require + Exclude []*Exclude + Replace []*Replace + + Syntax *FileSyntax +} + +// A Module is the module statement. +type Module struct { + Mod module.Version + Syntax *Line +} + +// A Go is the go statement. +type Go struct { + Version string // "1.23" + 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 + Syntax *Line +} + +// A Replace is a single replace statement. +type Replace struct { + Old module.Version + New module.Version + Syntax *Line +} + +func (f *File) AddModuleStmt(path string) error { + if f.Syntax == nil { + f.Syntax = new(FileSyntax) + } + if f.Module == nil { + f.Module = &Module{ + Mod: module.Version{Path: path}, + Syntax: f.Syntax.addLine(nil, "module", AutoQuote(path)), + } + } else { + f.Module.Mod.Path = path + f.Syntax.updateLine(f.Module.Syntax, "module", AutoQuote(path)) + } + return nil +} + +func (f *File) AddComment(text string) { + if f.Syntax == nil { + f.Syntax = new(FileSyntax) + } + f.Syntax.Stmt = append(f.Syntax.Stmt, &CommentBlock{ + Comments: Comments{ + Before: []Comment{ + { + Token: text, + }, + }, + }, + }) +} + +type VersionFixer func(path, version string) (string, error) + +// 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. +func Parse(file string, data []byte, fix VersionFixer) (*File, error) { + return parseToFile(file, data, fix, true) +} + +// ParseLax is like Parse but ignores unknown statements. +// It is used when parsing go.mod files other than the main module, +// under the theory that most statement types we add in the future will +// only apply in the main module, like exclude and replace, +// and so we get better gradual deployments if old go commands +// simply ignore those statements when found in go.mod files +// in dependencies. +func ParseLax(file string, data []byte, fix VersionFixer) (*File, error) { + return parseToFile(file, data, fix, false) +} + +func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File, error) { + fs, err := parse(file, data) + if err != nil { + return nil, err + } + f := &File{ + Syntax: fs, + } + + var errs bytes.Buffer + for _, x := range fs.Stmt { + switch x := x.(type) { + case *Line: + f.add(&errs, x, x.Token[0], x.Token[1:], fix, strict) + + case *LineBlock: + if len(x.Token) > 1 { + if strict { + fmt.Fprintf(&errs, "%s:%d: unknown block type: %s\n", file, x.Start.Line, strings.Join(x.Token, " ")) + } + continue + } + switch x.Token[0] { + default: + if strict { + fmt.Fprintf(&errs, "%s:%d: unknown block type: %s\n", file, x.Start.Line, strings.Join(x.Token, " ")) + } + continue + case "module", "require", "exclude", "replace": + for _, l := range x.Line { + f.add(&errs, l, x.Token[0], l.Token, fix, strict) + } + } + } + } + + if errs.Len() > 0 { + return nil, errors.New(strings.TrimRight(errs.String(), "\n")) + } + return f, nil +} + +var goVersionRE = regexp.MustCompile(`([1-9][0-9]*)\.(0|[1-9][0-9]*)`) + +func (f *File) add(errs *bytes.Buffer, line *Line, verb string, args []string, fix VersionFixer, strict bool) { + // If strict is false, this module is a dependency. + // We ignore all unknown directives as well as main-module-only + // directives like replace and exclude. It will work better for + // forward compatibility if we can depend on modules that have unknown + // statements (presumed relevant only when acting as the main module) + // and simply ignore those statements. + if !strict { + switch verb { + case "module", "require", "go": + // want these even for dependency go.mods + default: + return + } + } + + switch verb { + default: + fmt.Fprintf(errs, "%s:%d: unknown directive: %s\n", f.Syntax.Name, line.Start.Line, verb) + + case "go": + if f.Go != nil { + fmt.Fprintf(errs, "%s:%d: repeated go statement\n", f.Syntax.Name, line.Start.Line) + return + } + if len(args) != 1 || !goVersionRE.MatchString(args[0]) { + fmt.Fprintf(errs, "%s:%d: usage: go 1.23\n", f.Syntax.Name, line.Start.Line) + return + } + f.Go = &Go{Syntax: line} + f.Go.Version = args[0] + case "module": + if f.Module != nil { + fmt.Fprintf(errs, "%s:%d: repeated module statement\n", f.Syntax.Name, line.Start.Line) + return + } + f.Module = &Module{Syntax: line} + if len(args) != 1 { + + fmt.Fprintf(errs, "%s:%d: usage: module module/path [version]\n", f.Syntax.Name, line.Start.Line) + return + } + s, err := parseString(&args[0]) + if err != nil { + fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err) + return + } + f.Module.Mod = module.Version{Path: s} + case "require", "exclude": + if len(args) != 2 { + fmt.Fprintf(errs, "%s:%d: usage: %s module/path v1.2.3\n", f.Syntax.Name, line.Start.Line, verb) + return + } + s, err := parseString(&args[0]) + if err != nil { + fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err) + return + } + old := args[1] + v, err := parseVersion(s, &args[1], fix) + if err != nil { + fmt.Fprintf(errs, "%s:%d: invalid module version %q: %v\n", f.Syntax.Name, line.Start.Line, old, err) + return + } + pathMajor, err := modulePathMajor(s) + if err != nil { + fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err) + return + } + if !module.MatchPathMajor(v, pathMajor) { + if pathMajor == "" { + pathMajor = "v0 or v1" + } + fmt.Fprintf(errs, "%s:%d: invalid module: %s should be %s, not %s (%s)\n", f.Syntax.Name, line.Start.Line, s, pathMajor, semver.Major(v), v) + return + } + if verb == "require" { + f.Require = append(f.Require, &Require{ + Mod: module.Version{Path: s, Version: v}, + Syntax: line, + Indirect: isIndirect(line), + }) + } else { + f.Exclude = append(f.Exclude, &Exclude{ + Mod: module.Version{Path: s, Version: v}, + Syntax: line, + }) + } + case "replace": + arrow := 2 + if len(args) >= 2 && args[1] == "=>" { + arrow = 1 + } + if len(args) < arrow+2 || len(args) > arrow+3 || args[arrow] != "=>" { + fmt.Fprintf(errs, "%s:%d: usage: %s module/path [v1.2.3] => other/module v1.4\n\t or %s module/path [v1.2.3] => ../local/directory\n", f.Syntax.Name, line.Start.Line, verb, verb) + return + } + s, err := parseString(&args[0]) + if err != nil { + fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err) + return + } + pathMajor, err := modulePathMajor(s) + if err != nil { + fmt.Fprintf(errs, "%s:%d: %v\n", f.Syntax.Name, line.Start.Line, err) + return + } + var v string + if arrow == 2 { + old := args[1] + v, err = parseVersion(s, &args[1], fix) + if err != nil { + fmt.Fprintf(errs, "%s:%d: invalid module version %v: %v\n", f.Syntax.Name, line.Start.Line, old, err) + return + } + if !module.MatchPathMajor(v, pathMajor) { + if pathMajor == "" { + pathMajor = "v0 or v1" + } + fmt.Fprintf(errs, "%s:%d: invalid module: %s should be %s, not %s (%s)\n", f.Syntax.Name, line.Start.Line, s, pathMajor, semver.Major(v), v) + return + } + } + ns, err := parseString(&args[arrow+1]) + if err != nil { + fmt.Fprintf(errs, "%s:%d: invalid quoted string: %v\n", f.Syntax.Name, line.Start.Line, err) + return + } + nv := "" + if len(args) == arrow+2 { + if !IsDirectoryPath(ns) { + fmt.Fprintf(errs, "%s:%d: replacement module without version must be directory path (rooted or starting with ./ or ../)\n", f.Syntax.Name, line.Start.Line) + return + } + if filepath.Separator == '/' && strings.Contains(ns, `\`) { + fmt.Fprintf(errs, "%s:%d: replacement directory appears to be Windows path (on a non-windows system)\n", f.Syntax.Name, line.Start.Line) + return + } + } + if len(args) == arrow+3 { + old := args[arrow+1] + nv, err = parseVersion(ns, &args[arrow+2], fix) + if err != nil { + fmt.Fprintf(errs, "%s:%d: invalid module version %v: %v\n", f.Syntax.Name, line.Start.Line, old, err) + return + } + if IsDirectoryPath(ns) { + fmt.Fprintf(errs, "%s:%d: replacement module directory path %q cannot have version\n", f.Syntax.Name, line.Start.Line, ns) + return + } + } + f.Replace = append(f.Replace, &Replace{ + Old: module.Version{Path: s, Version: v}, + New: module.Version{Path: ns, Version: nv}, + Syntax: line, + }) + } +} + +// 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(line.Suffix[0].Token) + return (len(f) == 2 && f[1] == "indirect" || len(f) > 2 && f[1] == "indirect;") && f[0] == "//" +} + +// 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 + } + // Insert at beginning of existing comment. + com := &line.Suffix[0] + space := " " + if len(com.Token) > 2 && com.Token[2] == ' ' || com.Token[2] == '\t' { + space = "" + } + com.Token = "// indirect;" + space + com.Token[2:] + 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. +func IsDirectoryPath(ns string) bool { + // Because go.mod files can move from one system to another, + // we check all known path syntaxes, both Unix and Windows. + return strings.HasPrefix(ns, "./") || strings.HasPrefix(ns, "../") || strings.HasPrefix(ns, "/") || + strings.HasPrefix(ns, `.\`) || strings.HasPrefix(ns, `..\`) || strings.HasPrefix(ns, `\`) || + len(ns) >= 2 && ('A' <= ns[0] && ns[0] <= 'Z' || 'a' <= ns[0] && ns[0] <= 'z') && ns[1] == ':' +} + +// MustQuote reports whether s must be quoted in order to appear as +// a single token in a go.mod line. +func MustQuote(s string) bool { + for _, r := range s { + if !unicode.IsPrint(r) || r == ' ' || r == '"' || r == '\'' || r == '`' { + return true + } + } + return s == "" || strings.Contains(s, "//") || strings.Contains(s, "/*") +} + +// AutoQuote returns s or, if quoting is required for s to appear in a go.mod, +// the quotation of s. +func AutoQuote(s string) string { + if MustQuote(s) { + return strconv.Quote(s) + } + return s +} + +func parseString(s *string) (string, error) { + t := *s + if strings.HasPrefix(t, `"`) { + var err error + if t, err = strconv.Unquote(t); err != nil { + return "", err + } + } else if strings.ContainsAny(t, "\"'`") { + // Other quotes are reserved both for possible future expansion + // and to avoid confusion. For example if someone types 'x' + // we want that to be a syntax error and not a literal x in literal quotation marks. + return "", fmt.Errorf("unquoted string cannot contain quote") + } + *s = AutoQuote(t) + return t, nil +} + +func parseVersion(path string, s *string, fix VersionFixer) (string, error) { + t, err := parseString(s) + if err != nil { + return "", err + } + if fix != nil { + var err error + t, err = fix(path, t) + if err != nil { + return "", err + } + } + if v := module.CanonicalVersion(t); v != "" { + *s = v + return *s, nil + } + return "", fmt.Errorf("version must be of the form v1.2.3") +} + +func modulePathMajor(path string) (string, error) { + _, major, ok := module.SplitPathVersion(path) + if !ok { + return "", fmt.Errorf("invalid module path") + } + return major, nil +} + +func (f *File) Format() ([]byte, error) { + return Format(f.Syntax), nil +} + +// Cleanup cleans up the file f after any edit operations. +// To avoid quadratic behavior, modifications like DropRequire +// clear the entry but do not remove it from the slice. +// Cleanup cleans out all the cleared entries. +func (f *File) Cleanup() { + w := 0 + for _, r := range f.Require { + if r.Mod.Path != "" { + f.Require[w] = r + w++ + } + } + f.Require = f.Require[:w] + + w = 0 + for _, x := range f.Exclude { + if x.Mod.Path != "" { + f.Exclude[w] = x + w++ + } + } + f.Exclude = f.Exclude[:w] + + w = 0 + for _, r := range f.Replace { + if r.Old.Path != "" { + f.Replace[w] = r + w++ + } + } + f.Replace = f.Replace[:w] + + f.Syntax.Cleanup() +} + +func (f *File) AddRequire(path, vers string) error { + need := true + for _, r := range f.Require { + if r.Mod.Path == path { + if need { + r.Mod.Version = vers + f.Syntax.updateLine(r.Syntax, "require", AutoQuote(path), vers) + need = false + } else { + f.Syntax.removeLine(r.Syntax) + *r = Require{} + } + } + } + + if need { + f.AddNewRequire(path, vers, false) + } + return nil +} + +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}) +} + +func (f *File) SetRequire(req []*Require) { + need := make(map[string]string) + indirect := make(map[string]bool) + for _, r := range req { + need[r.Mod.Path] = r.Mod.Version + indirect[r.Mod.Path] = r.Indirect + } + + for _, r := range f.Require { + if v, ok := need[r.Mod.Path]; ok { + r.Mod.Version = v + r.Indirect = indirect[r.Mod.Path] + } + } + + var newStmts []Expr + for _, stmt := range f.Syntax.Stmt { + switch stmt := stmt.(type) { + case *LineBlock: + if len(stmt.Token) > 0 && stmt.Token[0] == "require" { + var newLines []*Line + for _, line := range stmt.Line { + if p, err := parseString(&line.Token[0]); err == nil && need[p] != "" { + line.Token[1] = need[p] + delete(need, p) + setIndirect(line, indirect[p]) + newLines = append(newLines, line) + } + } + if len(newLines) == 0 { + continue // drop stmt + } + stmt.Line = newLines + } + + 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]) + } else { + continue // drop stmt + } + } + } + newStmts = append(newStmts, stmt) + } + f.Syntax.Stmt = newStmts + + for path, vers := range need { + f.AddNewRequire(path, vers, indirect[path]) + } + f.SortBlocks() +} + +func (f *File) DropRequire(path string) error { + for _, r := range f.Require { + if r.Mod.Path == path { + f.Syntax.removeLine(r.Syntax) + *r = Require{} + } + } + return nil +} + +func (f *File) AddExclude(path, vers string) error { + var hint *Line + for _, x := range f.Exclude { + if x.Mod.Path == path && x.Mod.Version == vers { + return nil + } + if x.Mod.Path == path { + hint = x.Syntax + } + } + + f.Exclude = append(f.Exclude, &Exclude{Mod: module.Version{Path: path, Version: vers}, Syntax: f.Syntax.addLine(hint, "exclude", AutoQuote(path), vers)}) + return nil +} + +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 = Exclude{} + } + } + return nil +} + +func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error { + need := true + old := module.Version{Path: oldPath, Version: oldVers} + new := module.Version{Path: newPath, Version: newVers} + tokens := []string{"replace", AutoQuote(oldPath)} + if oldVers != "" { + tokens = append(tokens, oldVers) + } + tokens = append(tokens, "=>", AutoQuote(newPath)) + if newVers != "" { + tokens = append(tokens, newVers) + } + + var hint *Line + for _, r := range f.Replace { + if r.Old.Path == oldPath && (oldVers == "" || r.Old.Version == oldVers) { + if need { + // Found replacement for old; update to use new. + r.New = new + f.Syntax.updateLine(r.Syntax, tokens...) + need = false + continue + } + // Already added; delete other replacements for same. + f.Syntax.removeLine(r.Syntax) + *r = Replace{} + } + if r.Old.Path == oldPath { + hint = r.Syntax + } + } + if need { + f.Replace = append(f.Replace, &Replace{Old: old, New: new, Syntax: f.Syntax.addLine(hint, tokens...)}) + } + return nil +} + +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 = Replace{} + } + } + return nil +} + +func (f *File) SortBlocks() { + f.removeDups() // otherwise sorting is unsafe + + for _, stmt := range f.Syntax.Stmt { + block, ok := stmt.(*LineBlock) + if !ok { + continue + } + sort.Slice(block.Line, func(i, j int) bool { + li := block.Line[i] + lj := block.Line[j] + for k := 0; k < len(li.Token) && k < len(lj.Token); k++ { + if li.Token[k] != lj.Token[k] { + return li.Token[k] < lj.Token[k] + } + } + return len(li.Token) < len(lj.Token) + }) + } +} + +func (f *File) removeDups() { + have := make(map[module.Version]bool) + kill := make(map[*Line]bool) + for _, x := range f.Exclude { + if have[x.Mod] { + kill[x.Syntax] = true + continue + } + have[x.Mod] = true + } + var excl []*Exclude + for _, x := range f.Exclude { + if !kill[x.Syntax] { + excl = append(excl, x) + } + } + f.Exclude = excl + + have = make(map[module.Version]bool) + // Later replacements take priority over earlier ones. + for i := len(f.Replace) - 1; i >= 0; i-- { + x := f.Replace[i] + if have[x.Old] { + kill[x.Syntax] = true + continue + } + have[x.Old] = true + } + var repl []*Replace + for _, x := range f.Replace { + if !kill[x.Syntax] { + repl = append(repl, x) + } + } + f.Replace = repl + + var stmts []Expr + for _, stmt := range f.Syntax.Stmt { + switch stmt := stmt.(type) { + case *Line: + if kill[stmt] { + continue + } + case *LineBlock: + var lines []*Line + for _, line := range stmt.Line { + if !kill[line] { + lines = append(lines, line) + } + } + stmt.Line = lines + if len(lines) == 0 { + continue + } + } + stmts = append(stmts, stmt) + } + f.Syntax.Stmt = stmts +} diff --git a/libgo/go/cmd/go/internal/modfile/rule_test.go b/libgo/go/cmd/go/internal/modfile/rule_test.go new file mode 100644 index 00000000000..b88ad629168 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/rule_test.go @@ -0,0 +1,90 @@ +// 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 modfile + +import ( + "bytes" + "fmt" + "testing" +) + +var addRequireTests = []struct { + in string + path string + vers string + out string +}{ + { + ` + module m + require x.y/z v1.2.3 + `, + "x.y/z", "v1.5.6", + ` + module m + require x.y/z v1.5.6 + `, + }, + { + ` + module m + require x.y/z v1.2.3 + `, + "x.y/w", "v1.5.6", + ` + module m + require ( + x.y/z v1.2.3 + x.y/w v1.5.6 + ) + `, + }, + { + ` + module m + require x.y/z v1.2.3 + require x.y/q/v2 v2.3.4 + `, + "x.y/w", "v1.5.6", + ` + module m + require x.y/z v1.2.3 + require ( + x.y/q/v2 v2.3.4 + x.y/w v1.5.6 + ) + `, + }, +} + +func TestAddRequire(t *testing.T) { + for i, tt := range addRequireTests { + t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) { + f, err := Parse("in", []byte(tt.in), nil) + if err != nil { + t.Fatal(err) + } + g, err := Parse("out", []byte(tt.out), nil) + if err != nil { + t.Fatal(err) + } + golden, err := g.Format() + if err != nil { + t.Fatal(err) + } + + if err := f.AddRequire(tt.path, tt.vers); err != nil { + t.Fatal(err) + } + out, err := f.Format() + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(out, golden) { + t.Errorf("have:\n%s\nwant:\n%s", out, golden) + } + }) + } +} diff --git a/libgo/go/cmd/go/internal/modfile/testdata/block.golden b/libgo/go/cmd/go/internal/modfile/testdata/block.golden new file mode 100644 index 00000000000..4aa2d634fc9 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/block.golden @@ -0,0 +1,29 @@ +// comment +x "y" z + +// block +block ( // block-eol + // x-before-line + + "x" ( y // x-eol + "x1" + "x2" + // line + "x3" + "x4" + + "x5" + + // y-line + "y" // y-eol + + "z" // z-eol +) // block-eol2 + +block2 ( + x + y + z +) + +// eof diff --git a/libgo/go/cmd/go/internal/modfile/testdata/block.in b/libgo/go/cmd/go/internal/modfile/testdata/block.in new file mode 100644 index 00000000000..1dfae65f5c0 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/block.in @@ -0,0 +1,29 @@ +// comment +x "y" z + +// block +block ( // block-eol + // x-before-line + + "x" ( y // x-eol + "x1" + "x2" + // line + "x3" + "x4" + + "x5" + + // y-line + "y" // y-eol + + "z" // z-eol +) // block-eol2 + + +block2 (x + y + z +) + +// eof diff --git a/libgo/go/cmd/go/internal/modfile/testdata/comment.golden b/libgo/go/cmd/go/internal/modfile/testdata/comment.golden new file mode 100644 index 00000000000..75f3b84478c --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/comment.golden @@ -0,0 +1,10 @@ +// comment +module "x" // eol + +// mid comment + +// comment 2 +// comment 2 line 2 +module "y" // eoy + +// comment 3 diff --git a/libgo/go/cmd/go/internal/modfile/testdata/comment.in b/libgo/go/cmd/go/internal/modfile/testdata/comment.in new file mode 100644 index 00000000000..bfc2492b264 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/comment.in @@ -0,0 +1,8 @@ +// comment +module "x" // eol +// mid comment + +// comment 2 +// comment 2 line 2 +module "y" // eoy +// comment 3 diff --git a/libgo/go/cmd/go/internal/modfile/testdata/empty.golden b/libgo/go/cmd/go/internal/modfile/testdata/empty.golden new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libgo/go/cmd/go/internal/modfile/testdata/empty.in b/libgo/go/cmd/go/internal/modfile/testdata/empty.in new file mode 100644 index 00000000000..e69de29bb2d diff --git a/libgo/go/cmd/go/internal/modfile/testdata/gopkg.in.golden b/libgo/go/cmd/go/internal/modfile/testdata/gopkg.in.golden new file mode 100644 index 00000000000..41669b3a737 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/gopkg.in.golden @@ -0,0 +1,6 @@ +module x + +require ( + gopkg.in/mgo.v2 v2.0.0-20160818020120-3f83fa500528 + gopkg.in/yaml.v2 v2.2.1 +) diff --git a/libgo/go/cmd/go/internal/modfile/testdata/module.golden b/libgo/go/cmd/go/internal/modfile/testdata/module.golden new file mode 100644 index 00000000000..78ba94398c3 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/module.golden @@ -0,0 +1 @@ +module abc diff --git a/libgo/go/cmd/go/internal/modfile/testdata/module.in b/libgo/go/cmd/go/internal/modfile/testdata/module.in new file mode 100644 index 00000000000..08f383623f9 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/module.in @@ -0,0 +1 @@ +module "abc" diff --git a/libgo/go/cmd/go/internal/modfile/testdata/replace.golden b/libgo/go/cmd/go/internal/modfile/testdata/replace.golden new file mode 100644 index 00000000000..5d6abcfcdad --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/replace.golden @@ -0,0 +1,5 @@ +module abc + +replace xyz v1.2.3 => /tmp/z + +replace xyz v1.3.4 => my/xyz v1.3.4-me diff --git a/libgo/go/cmd/go/internal/modfile/testdata/replace.in b/libgo/go/cmd/go/internal/modfile/testdata/replace.in new file mode 100644 index 00000000000..685249946a2 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/replace.in @@ -0,0 +1,5 @@ +module "abc" + +replace "xyz" v1.2.3 => "/tmp/z" + +replace "xyz" v1.3.4 => "my/xyz" v1.3.4-me diff --git a/libgo/go/cmd/go/internal/modfile/testdata/replace2.golden b/libgo/go/cmd/go/internal/modfile/testdata/replace2.golden new file mode 100644 index 00000000000..e1d9c728df4 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/replace2.golden @@ -0,0 +1,10 @@ +module abc + +replace ( + xyz v1.2.3 => /tmp/z + xyz v1.3.4 => my/xyz v1.3.4-me + xyz v1.4.5 => "/tmp/my dir" + xyz v1.5.6 => my/xyz v1.5.6 + + xyz => my/other/xyz v1.5.4 +) diff --git a/libgo/go/cmd/go/internal/modfile/testdata/replace2.in b/libgo/go/cmd/go/internal/modfile/testdata/replace2.in new file mode 100644 index 00000000000..786469866f9 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/replace2.in @@ -0,0 +1,10 @@ +module "abc" + +replace ( + "xyz" v1.2.3 => "/tmp/z" + "xyz" v1.3.4 => "my/xyz" "v1.3.4-me" + xyz "v1.4.5" => "/tmp/my dir" + xyz v1.5.6 => my/xyz v1.5.6 + + xyz => my/other/xyz v1.5.4 +) diff --git a/libgo/go/cmd/go/internal/modfile/testdata/rule1.golden b/libgo/go/cmd/go/internal/modfile/testdata/rule1.golden new file mode 100644 index 00000000000..8a5c7258948 --- /dev/null +++ b/libgo/go/cmd/go/internal/modfile/testdata/rule1.golden @@ -0,0 +1,7 @@ +module "x" + +module "y" + +require "x" + +require x diff --git a/libgo/go/cmd/go/internal/modget/get.go b/libgo/go/cmd/go/internal/modget/get.go new file mode 100644 index 00000000000..90a5bd81302 --- /dev/null +++ b/libgo/go/cmd/go/internal/modget/get.go @@ -0,0 +1,656 @@ +// 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 modget implements the module-aware ``go get'' command. +package modget + +import ( + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/get" + "cmd/go/internal/load" + "cmd/go/internal/modfetch" + "cmd/go/internal/modload" + "cmd/go/internal/module" + "cmd/go/internal/mvs" + "cmd/go/internal/par" + "cmd/go/internal/search" + "cmd/go/internal/semver" + "cmd/go/internal/str" + "cmd/go/internal/work" + "fmt" + "os" + pathpkg "path" + "path/filepath" + "strings" +) + +var CmdGet = &base.Command{ + // Note: -d -m -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] [-m] [-u] [-v] [-insecure] [build flags] [packages]", + Short: "add dependencies to current module and install them", + Long: ` +Get resolves and adds dependencies to the current development module +and then builds and installs them. + +The first step is to resolve which dependencies to add. + +For each named package or package pattern, get must decide which version of +the corresponding module to use. By default, get chooses the latest tagged +release version, such as v0.4.5 or v1.2.3. If there are no tagged release +versions, get chooses the latest tagged prerelease version, such as +v0.0.1-pre1. If there are no tagged versions at all, get chooses the latest +known commit. + +This default version selection can be overridden by adding an @version +suffix to the package argument, as in 'go get golang.org/x/text@v0.3.0'. +For modules stored in source control repositories, the version suffix can +also be a commit hash, branch identifier, or other syntax known to the +source control system, as in 'go get golang.org/x/text@master'. +The version suffix @latest explicitly requests the default behavior +described above. + +If a module under consideration is already a dependency of the current +development module, then get will update the required version. +Specifying a version earlier than the current required version is valid and +downgrades the dependency. The version suffix @none indicates that the +dependency should be removed entirely. + +Although get defaults to using the latest version of the module containing +a named package, it does not use the latest version of that module's +dependencies. Instead it prefers to use the specific dependency versions +requested by that module. For example, if the latest A requires module +B v1.2.3, while B v1.2.4 and v1.3.1 are also available, then 'go get A' +will use the latest A but then use B v1.2.3, as requested by A. (If there +are competing requirements for a particular module, then 'go get' resolves +those requirements by taking the maximum requested version.) + +The -u flag instructs get to update dependencies to use newer minor or +patch releases when available. Continuing the previous example, +'go get -u A' will use the latest A with B v1.3.1 (not B v1.2.3). + +The -u=patch flag (not -u patch) instructs get to update dependencies +to use newer patch releases when available. Continuing the previous example, +'go get -u=patch A' will use the latest A with B v1.2.4 (not B v1.2.3). + +In general, adding a new dependency may require upgrading +existing dependencies to keep a working build, and 'go get' does +this automatically. Similarly, downgrading one dependency may +require downgrading other dependenceis, and 'go get' does +this automatically as well. + +The -m flag instructs get to stop here, after resolving, upgrading, +and downgrading modules and updating go.mod. When using -m, +each specified package path must be a module path as well, +not the import path of a package below the module root. + +The -insecure flag permits fetching from repositories and resolving +custom domains using insecure schemes such as HTTP. Use with caution. + +The second step is to download (if needed), build, and install +the named packages. + +If an argument names a module but not a package (because there is no +Go source code in the module's root directory), then the install step +is skipped for that argument, instead of causing a build failure. +For example 'go get golang.org/x/perf' succeeds even though there +is no code corresponding to that import path. + +Note that package patterns are allowed and are expanded after resolving +the module versions. For example, 'go get golang.org/x/perf/cmd/...' +adds the latest golang.org/x/perf and then installs the commands in that +latest version. + +The -d flag instructs get to download the source code needed to build +the named packages, including downloading necessary dependencies, +but not to build and install them. + +With no package arguments, 'go get' applies to the main module, +and to the Go package in the current directory, if any. In particular, +'go get -u' and 'go get -u=patch' update all the dependencies of the +main module. With no package arguments and also without -u, +'go get' is not much more than 'go install', and 'go get -d' not much +more than 'go list'. + +For more about modules, see 'go help modules'. + +For more about specifying packages, see 'go help packages'. + +This text describes the behavior of get using modules to manage source +code and dependencies. If instead the go command is running in GOPATH +mode, the details of get's flags and effects change, as does 'go help get'. +See 'go help modules' and 'go help gopath-get'. + +See also: go build, go install, go clean, go mod. + `, +} + +// Note that this help text is a stopgap to make the module-aware get help text +// available even in non-module settings. It should be deleted when the old get +// is deleted. It should NOT be considered to set a precedent of having hierarchical +// help names with dashes. +var HelpModuleGet = &base.Command{ + UsageLine: "module-get", + Short: "module-aware go get", + Long: ` +The 'go get' command changes behavior depending on whether the +go command is running in module-aware mode or legacy GOPATH mode. +This help text, accessible as 'go help module-get' even in legacy GOPATH mode, +describes 'go get' as it operates in module-aware mode. + +Usage: ` + CmdGet.UsageLine + ` +` + CmdGet.Long, +} + +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 get.Insecure + // -v is cfg.BuildV +) + +// upgradeFlag is a custom flag.Value for -u. +type upgradeFlag string + +func (*upgradeFlag) IsBoolFlag() bool { return true } // allow -u + +func (v *upgradeFlag) Set(s string) error { + if s == "false" { + s = "" + } + *v = upgradeFlag(s) + return nil +} + +func (v *upgradeFlag) String() string { return "" } + +func init() { + work.AddBuildFlags(CmdGet) + CmdGet.Run = runGet // break init loop + CmdGet.Flag.BoolVar(&get.Insecure, "insecure", get.Insecure, "") + CmdGet.Flag.Var(&getU, "u", "") +} + +// A task holds the state for processing a single get argument (path@vers). +type task struct { + arg string // original argument + index int + path string // package path part of arg + forceModulePath bool // path must be interpreted as a module path + vers string // version part of arg + m module.Version // module version indicated by argument + req []module.Version // m's requirement list (not upgraded) +} + +func runGet(cmd *base.Command, args []string) { + // -mod=readonly has no effect on "go get". + if cfg.BuildMod == "readonly" { + cfg.BuildMod = "" + } + + switch getU { + case "", "patch", "true": + // ok + default: + base.Fatalf("go get: unknown upgrade flag -u=%s", getU) + } + if *getF { + fmt.Fprintf(os.Stderr, "go get: -f flag is a no-op when using modules\n") + } + if *getFix { + fmt.Fprintf(os.Stderr, "go get: -fix flag is a no-op when using modules\n") + } + if *getT { + fmt.Fprintf(os.Stderr, "go get: -t flag is a no-op when using modules\n") + } + + if cfg.BuildMod == "vendor" { + base.Fatalf("go get: disabled by -mod=%s", cfg.BuildMod) + } + + modload.LoadBuildList() + + // Do not allow any updating of go.mod until we've applied + // all the requested changes and checked that the result matches + // what was requested. + modload.DisallowWriteGoMod() + + // Build task and install lists. + // The command-line arguments are of the form path@version + // or simply path, with implicit @latest. path@none is "downgrade away". + // At the end of the loop, we've resolved the list of arguments into + // a list of tasks (a path@vers that needs further processing) + // and a list of install targets (for the "go install" at the end). + var tasks []*task + var install []string + for _, arg := range search.CleanPatterns(args) { + // Argument is module query path@vers, or else path with implicit @latest. + path := arg + vers := "" + if i := strings.Index(arg, "@"); i >= 0 { + path, vers = arg[:i], arg[i+1:] + } + if strings.Contains(vers, "@") || arg != path && vers == "" { + base.Errorf("go get %s: invalid module version syntax", arg) + continue + } + if vers != "none" { + install = append(install, path) + } + + // Deciding which module to upgrade/downgrade for a particular argument is difficult. + // Patterns only make it more difficult. + // We impose restrictions to avoid needing to interlace pattern expansion, + // like in in modload.ImportPaths. + // Specifically, these patterns are supported: + // + // - Relative paths like ../../foo or ../../foo... are restricted to matching directories + // in the current module and therefore map to the current module. + // It's possible that the pattern matches no packages, but we will still treat it + // as mapping to the current module. + // TODO: In followup, could just expand the full list and remove the discrepancy. + // - The pattern "all" has its usual package meaning and maps to the list of modules + // from which the matched packages are drawn. This is potentially a subset of the + // module pattern "all". If module A requires B requires C but A does not import + // the parts of B that import C, the packages matched by "all" are only from A and B, + // so only A and B end up on the tasks list. + // TODO: Even in -m mode? + // - The patterns "std" and "cmd" expand to packages in the standard library, + // which aren't upgradable, so we skip over those. + // In -m mode they expand to non-module-paths, so they are disallowed. + // - Import path patterns like foo/bar... are matched against the module list, + // assuming any package match would imply a module pattern match. + // TODO: What about -m mode? + // - Import paths without patterns are left as is, for resolution by getQuery (eventually modload.Import). + // + if search.IsRelativePath(path) { + // Check that this relative pattern only matches directories in the current module, + // and then record the current module as the target. + dir := path + if i := strings.Index(path, "..."); i >= 0 { + dir, _ = pathpkg.Split(path[:i]) + } + abs, err := filepath.Abs(dir) + if err != nil { + base.Errorf("go get %s: %v", arg, err) + continue + } + if !str.HasFilePathPrefix(abs, modload.ModRoot) { + base.Errorf("go get %s: directory %s is outside module root %s", arg, abs, modload.ModRoot) + continue + } + // TODO: Check if abs is inside a nested module. + tasks = append(tasks, &task{arg: arg, path: modload.Target.Path, vers: ""}) + continue + } + if path == "all" { + // TODO: If *getM, should this be the module pattern "all"? + + // This is the package pattern "all" not the module pattern "all": + // enumerate all the modules actually needed by builds of the packages + // in the main module, not incidental modules that happen to be + // in the package graph (and therefore build list). + // Note that LoadALL may add new modules to the build list to + // satisfy new imports, but vers == "latest" implicitly anyway, + // so we'll assume that's OK. + seen := make(map[module.Version]bool) + pkgs := modload.LoadALL() + for _, pkg := range pkgs { + m := modload.PackageModule(pkg) + if m.Path != "" && !seen[m] { + seen[m] = true + tasks = append(tasks, &task{arg: arg, path: m.Path, vers: "latest", forceModulePath: true}) + } + } + continue + } + if search.IsMetaPackage(path) { + // Already handled "all", so this must be "std" or "cmd", + // which are entirely in the standard library. + if path != arg { + base.Errorf("go get %s: cannot use pattern %q with explicit version", arg, arg) + } + if *getM { + base.Errorf("go get %s: cannot use pattern %q with -m", arg, arg) + continue + } + continue + } + if strings.Contains(path, "...") { + // Apply to modules in build list matched by pattern (golang.org/x/...), if any. + match := search.MatchPattern(path) + matched := false + for _, m := range modload.BuildList() { + if match(m.Path) || str.HasPathPrefix(path, m.Path) { + tasks = append(tasks, &task{arg: arg, path: m.Path, vers: vers, forceModulePath: true}) + matched = true + } + } + // If matched, we're done. + // Otherwise assume pattern is inside a single module + // (golang.org/x/text/unicode/...) and leave for usual lookup. + // Unless we're using -m. + if matched { + continue + } + if *getM { + base.Errorf("go get %s: pattern matches no modules in build list", arg) + continue + } + } + tasks = append(tasks, &task{arg: arg, path: path, vers: vers}) + } + base.ExitIfErrors() + + // Now we've reduced the upgrade/downgrade work to a list of path@vers pairs (tasks). + // Resolve each one in parallel. + reqs := modload.Reqs() + var lookup par.Work + for _, t := range tasks { + lookup.Add(t) + } + lookup.Do(10, func(item interface{}) { + t := item.(*task) + if t.vers == "none" { + // Wait for downgrade step. + t.m = module.Version{Path: t.path, Version: "none"} + return + } + m, err := getQuery(t.path, t.vers, t.forceModulePath) + if err != nil { + base.Errorf("go get %v: %v", t.arg, err) + return + } + t.m = m + }) + base.ExitIfErrors() + + // Now we know the specific version of each path@vers. + // The final build list will be the union of three build lists: + // 1. the original build list + // 2. the modules named on the command line (other than @none) + // 3. the upgraded requirements of those modules (if upgrading) + // Start building those lists. + // This loop collects (2). + // Also, because the list of paths might have named multiple packages in a single module + // (or even the same package multiple times), now that we know the module for each + // package, this loop deduplicates multiple references to a given module. + // (If a module is mentioned multiple times, the listed target version must be the same each time.) + var named []module.Version + byPath := make(map[string]*task) + for _, t := range tasks { + prev, ok := byPath[t.m.Path] + if prev != nil && prev.m != t.m { + base.Errorf("go get: conflicting versions for module %s: %s and %s", t.m.Path, prev.m.Version, t.m.Version) + byPath[t.m.Path] = nil // sentinel to stop errors + continue + } + if ok { + continue // already added + } + byPath[t.m.Path] = t + if t.m.Version != "none" { + named = append(named, t.m) + } + } + base.ExitIfErrors() + + // If the modules named on the command line have any dependencies + // and we're supposed to upgrade dependencies, + // chase down the full list of upgraded dependencies. + // This turns required from a not-yet-upgraded (3) to the final (3). + // (See list above.) + var required []module.Version + if getU != "" { + upgraded, err := mvs.UpgradeAll(upgradeTarget, &upgrader{ + Reqs: modload.Reqs(), + targets: named, + patch: getU == "patch", + tasks: byPath, + }) + if err != nil { + base.Fatalf("go get: %v", err) + } + required = upgraded[1:] // slice off upgradeTarget + base.ExitIfErrors() + } + + // Put together the final build list as described above (1) (2) (3). + // If we're not using -u, then len(required) == 0 and ReloadBuildList + // chases down the dependencies of all the named module versions + // in one operation. + var list []module.Version + list = append(list, modload.BuildList()...) + list = append(list, named...) + list = append(list, required...) + modload.SetBuildList(list) + modload.ReloadBuildList() // note: does not update go.mod + base.ExitIfErrors() + + // Scan for and apply any needed downgrades. + var down []module.Version + for _, m := range modload.BuildList() { + t := byPath[m.Path] + if t != nil && semver.Compare(m.Version, t.m.Version) > 0 { + down = append(down, module.Version{Path: m.Path, Version: t.m.Version}) + } + } + if len(down) > 0 { + list, err := mvs.Downgrade(modload.Target, modload.Reqs(), down...) + if err != nil { + base.Fatalf("go get: %v", err) + } + modload.SetBuildList(list) + modload.ReloadBuildList() // note: does not update go.mod + } + base.ExitIfErrors() + + // Scan for any upgrades lost by the downgrades. + lost := make(map[string]string) + for _, m := range modload.BuildList() { + t := byPath[m.Path] + if t != nil && semver.Compare(m.Version, t.m.Version) != 0 { + lost[m.Path] = m.Version + } + } + if len(lost) > 0 { + desc := func(m module.Version) string { + s := m.Path + "@" + m.Version + t := byPath[m.Path] + if t != nil && t.arg != s { + s += " from " + t.arg + } + return s + } + downByPath := make(map[string]module.Version) + for _, d := range down { + downByPath[d.Path] = d + } + var buf strings.Builder + fmt.Fprintf(&buf, "go get: inconsistent versions:") + for _, t := range tasks { + if lost[t.m.Path] == "" { + continue + } + // We lost t because its build list requires a newer version of something in down. + // Figure out exactly what. + // Repeatedly constructing the build list is inefficient + // if there are MANY command-line arguments, + // but at least all the necessary requirement lists are cached at this point. + list, err := mvs.BuildList(t.m, reqs) + if err != nil { + base.Fatalf("go get: %v", err) + } + + fmt.Fprintf(&buf, "\n\t%s", desc(t.m)) + sep := " requires" + for _, m := range list { + if down, ok := downByPath[m.Path]; ok && semver.Compare(down.Version, m.Version) < 0 { + fmt.Fprintf(&buf, "%s %s@%s (not %s)", sep, m.Path, m.Version, desc(down)) + sep = "," + } + } + if sep != "," { + // We have no idea why this happened. + // At least report the problem. + fmt.Fprintf(&buf, " ended up at %v unexpectedly (please report at golang.org/issue/new)", lost[t.m.Path]) + } + } + base.Fatalf("%v", buf.String()) + } + + // Everything succeeded. Update go.mod. + modload.AllowWriteGoMod() + modload.WriteGoMod() + + // If -m was specified, we're done after the module work. No download, no build. + if *getM { + return + } + + if len(install) > 0 { + // All requested versions were explicitly @none. + // Note that 'go get -u' without any arguments results in len(install) == 1: + // search.CleanImportPaths returns "." for empty args. + work.BuildInit() + pkgs := load.PackagesAndErrors(install) + var todo []*load.Package + for _, p := range pkgs { + // Ignore "no Go source files" errors for 'go get' operations on modules. + if p.Error != nil { + if len(args) == 0 && getU != "" && strings.HasPrefix(p.Error.Err, "no Go files") { + // Upgrading modules: skip the implicitly-requested package at the + // current directory, even if it is not tho module root. + continue + } + if strings.Contains(p.Error.Err, "cannot find module providing") && modload.ModuleInfo(p.ImportPath) != nil { + // Explicitly-requested module, but it doesn't contain a package at the + // module root. + continue + } + } + todo = append(todo, p) + } + + // If -d was specified, we're done after the download: no build. + // (The load.PackagesAndErrors is what did the download + // of the named packages and their dependencies.) + if len(todo) > 0 && !*getD { + work.InstallPackages(install, todo) + } + } +} + +// getQuery evaluates the given package path, version pair +// to determine the underlying module version being requested. +// If forceModulePath is set, getQuery must interpret path +// as a module path. +func getQuery(path, vers string, forceModulePath bool) (module.Version, error) { + if vers == "" { + vers = "latest" + } + + // First choice is always to assume path is a module path. + // If that works out, we're done. + info, err := modload.Query(path, vers, modload.Allowed) + if err == nil { + return module.Version{Path: path, Version: info.Version}, nil + } + + // Even if the query fails, if the path must be a real module, then report the query error. + if forceModulePath || *getM { + return module.Version{}, err + } + + // Otherwise, try a package path. + m, _, err := modload.QueryPackage(path, vers, modload.Allowed) + return m, err +} + +// An upgrader adapts an underlying mvs.Reqs to apply an +// upgrade policy to a list of targets and their dependencies. +// If patch=false, the upgrader implements "get -u". +// If patch=true, the upgrader implements "get -u=patch". +type upgrader struct { + mvs.Reqs + targets []module.Version + patch bool + tasks map[string]*task +} + +// upgradeTarget is a fake "target" requiring all the modules to be upgraded. +var upgradeTarget = module.Version{Path: "upgrade target", Version: ""} + +// Required returns the requirement list for m. +// Other than the upgradeTarget, we defer to u.Reqs. +func (u *upgrader) Required(m module.Version) ([]module.Version, error) { + if m == upgradeTarget { + return u.targets, nil + } + return u.Reqs.Required(m) +} + +// Upgrade returns the desired upgrade for m. +// If m is a tagged version, then Upgrade returns the latest tagged version. +// If m is a pseudo-version, then Upgrade returns the latest tagged version +// when that version has a time-stamp newer than m. +// Otherwise Upgrade returns m (preserving the pseudo-version). +// This special case prevents accidental downgrades +// when already using a pseudo-version newer than the latest tagged version. +func (u *upgrader) Upgrade(m module.Version) (module.Version, error) { + // Allow pkg@vers on the command line to override the upgrade choice v. + // If t's version is < v, then we're going to downgrade anyway, + // and it's cleaner to avoid moving back and forth and picking up + // extraneous other newer dependencies. + // If t's version is > v, then we're going to upgrade past v anyway, + // and again it's cleaner to avoid moving back and forth picking up + // extraneous other newer dependencies. + if t := u.tasks[m.Path]; t != nil { + return t.m, nil + } + + // Note that query "latest" is not the same as + // using repo.Latest. + // The query only falls back to untagged versions + // if nothing is tagged. The Latest method + // only ever returns untagged versions, + // which is not what we want. + query := "latest" + if u.patch { + // For patch upgrade, query "v1.2". + query = semver.MajorMinor(m.Version) + } + info, err := modload.Query(m.Path, query, modload.Allowed) + if err != nil { + // Report error but return m, to let version selection continue. + // (Reporting the error will fail the command at the next base.ExitIfErrors.) + // Special case: if the error is "no matching versions" then don't + // even report the error. Because Query does not consider pseudo-versions, + // it may happen that we have a pseudo-version but during -u=patch + // the query v0.0 matches no versions (not even the one we're using). + if !strings.Contains(err.Error(), "no matching versions") { + base.Errorf("go get: upgrading %s@%s: %v", m.Path, m.Version, err) + } + return m, nil + } + + // If we're on a later prerelease, keep using it, + // even though normally an Upgrade will ignore prereleases. + if semver.Compare(info.Version, m.Version) < 0 { + return m, nil + } + + // If we're on a pseudo-version chronologically after the latest tagged version, keep using it. + // This avoids some accidental downgrades. + if mTime, err := modfetch.PseudoVersionTime(m.Version); err == nil && info.Time.Before(mTime) { + return m, nil + } + + return module.Version{Path: m.Path, Version: info.Version}, nil +} diff --git a/libgo/go/cmd/go/internal/modinfo/info.go b/libgo/go/cmd/go/internal/modinfo/info.go new file mode 100644 index 00000000000..7341ce44d20 --- /dev/null +++ b/libgo/go/cmd/go/internal/modinfo/info.go @@ -0,0 +1,49 @@ +// 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 modinfo + +import "time" + +// Note that these structs are publicly visible (part of go list's API) +// 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 + Error *ModuleError `json:",omitempty"` // error loading module + GoVersion string `json:",omitempty"` // go version used in module +} + +type ModuleError struct { + Err string // error text +} + +func (m *ModulePublic) String() string { + s := m.Path + if m.Version != "" { + s += " " + m.Version + if m.Update != nil { + s += " [" + m.Update.Version + "]" + } + } + if m.Replace != nil { + s += " => " + m.Replace.Path + if m.Replace.Version != "" { + s += " " + m.Replace.Version + if m.Replace.Update != nil { + s += " [" + m.Replace.Update.Version + "]" + } + } + } + return s +} diff --git a/libgo/go/cmd/go/internal/modload/build.go b/libgo/go/cmd/go/internal/modload/build.go new file mode 100644 index 00000000000..558401d01f6 --- /dev/null +++ b/libgo/go/cmd/go/internal/modload/build.go @@ -0,0 +1,243 @@ +// 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 modload + +import ( + "bytes" + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/modfetch" + "cmd/go/internal/modinfo" + "cmd/go/internal/module" + "cmd/go/internal/search" + "encoding/hex" + "fmt" + "internal/goroot" + "os" + "path/filepath" + "strings" +) + +var ( + infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6") + infoEnd, _ = hex.DecodeString("f932433186182072008242104116d8f2") +) + +func isStandardImportPath(path string) bool { + return findStandardImportPath(path) != "" +} + +func findStandardImportPath(path string) string { + if search.IsStandardImportPath(path) { + if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) { + return filepath.Join(cfg.GOROOT, "src", path) + } + if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, "vendor/"+path) { + return filepath.Join(cfg.GOROOT, "src/vendor", path) + } + } + return "" +} + +func PackageModuleInfo(pkgpath string) *modinfo.ModulePublic { + if isStandardImportPath(pkgpath) || !Enabled() { + return nil + } + return moduleInfo(findModule(pkgpath, pkgpath), true) +} + +func ModuleInfo(path string) *modinfo.ModulePublic { + if !Enabled() { + return nil + } + + if i := strings.Index(path, "@"); i >= 0 { + return moduleInfo(module.Version{Path: path[:i], Version: path[i+1:]}, false) + } + + for _, m := range BuildList() { + if m.Path == path { + return moduleInfo(m, true) + } + } + + return &modinfo.ModulePublic{ + Path: path, + Error: &modinfo.ModuleError{ + Err: "module not in current build", + }, + } +} + +// addUpdate fills in m.Update if an updated version is available. +func addUpdate(m *modinfo.ModulePublic) { + if m.Version != "" { + if info, err := Query(m.Path, "latest", Allowed); err == nil && info.Version != m.Version { + m.Update = &modinfo.ModulePublic{ + Path: m.Path, + Version: info.Version, + Time: &info.Time, + } + } + } +} + +// addVersions fills in m.Versions with the list of known versions. +func addVersions(m *modinfo.ModulePublic) { + m.Versions, _ = versions(m.Path) +} + +func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic { + if m == Target { + info := &modinfo.ModulePublic{ + Path: m.Path, + Version: m.Version, + Main: true, + Dir: ModRoot, + GoMod: filepath.Join(ModRoot, "go.mod"), + } + if modFile.Go != nil { + info.GoVersion = modFile.Go.Version + } + return info + } + + info := &modinfo.ModulePublic{ + Path: m.Path, + Version: m.Version, + Indirect: fromBuildList && loaded != nil && !loaded.direct[m.Path], + } + if loaded != nil { + info.GoVersion = loaded.goVersion[m.Path] + } + + if cfg.BuildMod == "vendor" { + info.Dir = filepath.Join(ModRoot, "vendor", m.Path) + return info + } + + // complete fills in the extra fields in m. + complete := func(m *modinfo.ModulePublic) { + if m.Version != "" { + if q, err := Query(m.Path, m.Version, nil); err != nil { + m.Error = &modinfo.ModuleError{Err: err.Error()} + } else { + m.Version = q.Version + m.Time = &q.Time + } + + mod := module.Version{Path: m.Path, Version: m.Version} + 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 { + if info, err := os.Stat(dir); err == nil && info.IsDir() { + m.Dir = dir + } + } + } + if cfg.BuildMod == "vendor" { + m.Dir = filepath.Join(ModRoot, "vendor", m.Path) + } + } + + complete(info) + + if fromBuildList { + if r := Replacement(m); r.Path != "" { + info.Replace = &modinfo.ModulePublic{ + Path: r.Path, + Version: r.Version, + GoVersion: info.GoVersion, + } + if r.Version == "" { + if filepath.IsAbs(r.Path) { + info.Replace.Dir = r.Path + } else { + info.Replace.Dir = filepath.Join(ModRoot, r.Path) + } + } + complete(info.Replace) + info.Dir = info.Replace.Dir + info.GoMod = filepath.Join(info.Dir, "go.mod") + info.Error = nil // ignore error loading original module version (it has been replaced) + } + } + + return info +} + +func PackageBuildInfo(path string, deps []string) string { + if isStandardImportPath(path) || !Enabled() { + return "" + } + target := findModule(path, path) + mdeps := make(map[module.Version]bool) + for _, dep := range deps { + if !isStandardImportPath(dep) { + mdeps[findModule(path, dep)] = true + } + } + var mods []module.Version + delete(mdeps, target) + for mod := range mdeps { + mods = append(mods, mod) + } + module.Sort(mods) + + var buf bytes.Buffer + fmt.Fprintf(&buf, "path\t%s\n", path) + tv := target.Version + if tv == "" { + tv = "(devel)" + } + fmt.Fprintf(&buf, "mod\t%s\t%s\t%s\n", target.Path, tv, modfetch.Sum(target)) + for _, mod := range mods { + mv := mod.Version + if mv == "" { + mv = "(devel)" + } + r := Replacement(mod) + h := "" + if r.Path == "" { + h = "\t" + modfetch.Sum(mod) + } + fmt.Fprintf(&buf, "dep\t%s\t%s%s\n", mod.Path, mod.Version, h) + if r.Path != "" { + fmt.Fprintf(&buf, "=>\t%s\t%s\t%s\n", r.Path, r.Version, modfetch.Sum(r)) + } + } + return buf.String() +} + +func findModule(target, path string) module.Version { + // TODO: This should use loaded. + if path == "." { + return buildList[0] + } + for _, mod := range buildList { + if maybeInModule(path, mod.Path) { + return mod + } + } + base.Fatalf("build %v: cannot find module for path %v", target, path) + panic("unreachable") +} + +func ModInfoProg(info string) []byte { + return []byte(fmt.Sprintf(` + package main + import _ "unsafe" + //go:linkname __debug_modinfo__ runtime/debug.modinfo + var __debug_modinfo__ string + func init() { + __debug_modinfo__ = %q + } + `, string(infoStart)+info+string(infoEnd))) +} diff --git a/libgo/go/cmd/go/internal/modload/help.go b/libgo/go/cmd/go/internal/modload/help.go new file mode 100644 index 00000000000..f2f34197244 --- /dev/null +++ b/libgo/go/cmd/go/internal/modload/help.go @@ -0,0 +1,462 @@ +// 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 modload + +import "cmd/go/internal/base" + +// TODO(rsc): The "module code layout" section needs to be written. + +var HelpModules = &base.Command{ + UsageLine: "modules", + Short: "modules, module versions, and more", + Long: ` +A module is a collection of related Go packages. +Modules are the unit of source code interchange and versioning. +The go command has direct support for working with modules, +including recording and resolving dependencies on other modules. +Modules replace the old GOPATH-based approach to specifying +which source files are used in a given build. + +Preliminary module support + +Go 1.11 includes preliminary support for Go modules, +including a new module-aware 'go get' command. +We intend to keep revising this support, while preserving compatibility, +until it can be declared official (no longer preliminary), +and then at a later point we may remove support for work +in GOPATH and the old 'go get' command. + +The quickest way to take advantage of the new Go 1.11 module support +is to check out your repository into a directory outside GOPATH/src, +create a go.mod file (described in the next section) there, and run +go commands from within that file tree. + +For more fine-grained control, the module support in Go 1.11 respects +a temporary environment variable, GO111MODULE, which can be set to one +of three string values: off, on, or auto (the default). +If GO111MODULE=off, then the go command never uses the +new module support. Instead it looks in vendor directories and GOPATH +to find dependencies; we now refer to this as "GOPATH mode." +If GO111MODULE=on, then the go command requires the use of modules, +never consulting GOPATH. We refer to this as the command being +module-aware or running in "module-aware mode". +If GO111MODULE=auto or is unset, then the go command enables or +disables module support based on the current directory. +Module support is enabled only when the current directory is outside +GOPATH/src and itself contains a go.mod file or is below a directory +containing a go.mod file. + +In module-aware mode, GOPATH no longer defines the meaning of imports +during a build, but it still stores downloaded dependencies (in GOPATH/pkg/mod) +and installed commands (in GOPATH/bin, unless GOBIN is set). + +Defining a module + +A module is defined by a tree of Go source files with a go.mod file +in the tree's root directory. The directory containing the go.mod file +is called the module root. Typically the module root will also correspond +to a source code repository root (but in general it need not). +The module is the set of all Go packages in the module root and its +subdirectories, but excluding subtrees with their own go.mod files. + +The "module path" is the import path prefix corresponding to the module root. +The go.mod file defines the module path and lists the specific versions +of other modules that should be used when resolving imports during a build, +by giving their module paths and versions. + +For example, this go.mod declares that the directory containing it is the root +of the module with path example.com/m, and it also declares that the module +depends on specific versions of golang.org/x/text and gopkg.in/yaml.v2: + + module example.com/m + + require ( + golang.org/x/text v0.3.0 + gopkg.in/yaml.v2 v2.1.0 + ) + +The go.mod file can also specify replacements and excluded versions +that only apply when building the module directly; they are ignored +when the module is incorporated into a larger build. +For more about the go.mod file, see 'go help go.mod'. + +To start a new module, simply create a go.mod file in the root of the +module's directory tree, containing only a module statement. +The 'go mod init' command can be used to do this: + + go mod init example.com/m + +In a project already using an existing dependency management tool like +godep, glide, or dep, 'go mod init' will also add require statements +matching the existing configuration. + +Once the go.mod file exists, no additional steps are required: +go commands like 'go build', 'go test', or even 'go list' will automatically +add new dependencies as needed to satisfy imports. + +The main module and the build list + +The "main module" is the module containing the directory where the go command +is run. The go command finds the module root by looking for a go.mod in the +current directory, or else the current directory's parent directory, +or else the parent's parent directory, and so on. + +The main module's go.mod file defines the precise set of packages available +for use by the go command, through require, replace, and exclude statements. +Dependency modules, found by following require statements, also contribute +to the definition of that set of packages, but only through their go.mod +files' require statements: any replace and exclude statements in dependency +modules are ignored. The replace and exclude statements therefore allow the +main module complete control over its own build, without also being subject +to complete control by dependencies. + +The set of modules providing packages to builds is called the "build list". +The build list initially contains only the main module. Then the go command +adds to the list the exact module versions required by modules already +on the list, recursively, until there is nothing left to add to the list. +If multiple versions of a particular module are added to the list, +then at the end only the latest version (according to semantic version +ordering) is kept for use in the build. + +The 'go list' command provides information about the main module +and the build list. For example: + + go list -m # print path of main module + go list -m -f={{.Dir}} # print root directory of main module + go list -m all # print build list + +Maintaining module requirements + +The go.mod file is meant to be readable and editable by both +programmers and tools. The go command itself automatically updates the go.mod file +to maintain a standard formatting and the accuracy of require statements. + +Any go command that finds an unfamiliar import will look up the module +containing that import and add the latest version of that module +to go.mod automatically. In most cases, therefore, it suffices to +add an import to source code and run 'go build', 'go test', or even 'go list': +as part of analyzing the package, the go command will discover +and resolve the import and update the go.mod file. + +Any go command can determine that a module requirement is +missing and must be added, even when considering only a single +package from the module. On the other hand, determining that a module requirement +is no longer necessary and can be deleted requires a full view of +all packages in the module, across all possible build configurations +(architectures, operating systems, build tags, and so on). +The 'go mod tidy' command builds that view and then +adds any missing module requirements and removes unnecessary ones. + +As part of maintaining the require statements in go.mod, the go command +tracks which ones provide packages imported directly by the current module +and which ones provide packages only used indirectly by other module +dependencies. Requirements needed only for indirect uses are marked with a +"// indirect" comment in the go.mod file. Indirect requirements are +automatically removed from the go.mod file once they are implied by other +direct requirements. Indirect requirements only arise when using modules +that fail to state some of their own dependencies or when explicitly +upgrading a module's dependencies ahead of its own stated requirements. + +Because of this automatic maintenance, the information in go.mod is an +up-to-date, readable description of the build. + +The 'go get' command updates go.mod to change the module versions used in a +build. An upgrade of one module may imply upgrading others, and similarly a +downgrade of one module may imply downgrading others. The 'go get' command +makes these implied changes as well. If go.mod is edited directly, commands +like 'go build' or 'go list' will assume that an upgrade is intended and +automatically make any implied upgrades and update go.mod to reflect them. + +The 'go mod' command provides other functionality for use in maintaining +and understanding modules and go.mod files. See 'go help mod'. + +The -mod build flag provides additional control over updating and use of go.mod. + +If invoked with -mod=readonly, the go command is disallowed from the implicit +automatic updating of go.mod described above. Instead, it fails when any changes +to go.mod are needed. This setting is most useful to check that go.mod does +not need updates, such as in a continuous integration and testing system. +The "go get" command remains permitted to update go.mod even with -mod=readonly, +and the "go mod" commands do not take the -mod flag (or any other build flags). + +If invoked with -mod=vendor, the go command assumes that the vendor +directory holds the correct copies of dependencies and ignores +the dependency descriptions in go.mod. + +Pseudo-versions + +The go.mod file and the go command more generally use semantic versions as +the standard form for describing module versions, so that versions can be +compared to determine which should be considered earlier or later than another. +A module version like v1.2.3 is introduced by tagging a revision in the +underlying source repository. Untagged revisions can be referred to +using a "pseudo-version" like v0.0.0-yyyymmddhhmmss-abcdefabcdef, +where the time is the commit time in UTC and the final suffix is the prefix +of the commit hash. The time portion ensures that two pseudo-versions can +be compared to determine which happened later, the commit hash identifes +the underlying commit, and the prefix (v0.0.0- in this example) is derived from +the most recent tagged version in the commit graph before this commit. + +There are three pseudo-version forms: + +vX.0.0-yyyymmddhhmmss-abcdefabcdef is used when there is no earlier +versioned commit with an appropriate major version before the target commit. +(This was originally the only form, so some older go.mod files use this form +even for commits that do follow tags.) + +vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef is used when the most +recent versioned commit before the target commit is vX.Y.Z-pre. + +vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef is used when the most +recent versioned commit before the target commit is vX.Y.Z. + +Pseudo-versions never need to be typed by hand: the go command will accept +the plain commit hash and translate it into a pseudo-version (or a tagged +version if available) automatically. This conversion is an example of a +module query. + +Module queries + +The go command accepts a "module query" in place of a module version +both on the command line and in the main module's go.mod file. +(After evaluating a query found in the main module's go.mod file, +the go command updates the file to replace the query with its result.) + +A fully-specified semantic version, such as "v1.2.3", +evaluates to that specific version. + +A semantic version prefix, such as "v1" or "v1.2", +evaluates to the latest available tagged version with that prefix. + +A semantic version comparison, such as "=v1.5.6", +evaluates to the available tagged version nearest to the comparison target +(the latest version for < and <=, the earliest version for > and >=). + +The string "latest" matches the latest available tagged version, +or else the underlying source repository's latest untagged revision. + +A revision identifier for the underlying source repository, +such as a commit hash prefix, revision tag, or branch name, +selects that specific code revision. If the revision is +also tagged with a semantic version, the query evaluates to +that semantic version. Otherwise the query evaluates to a +pseudo-version for the commit. + +All queries prefer release versions to pre-release versions. +For example, " good/thing v1.4.5 + +The verbs are module, to define the module path; require, to require +a particular module at a given version or later; exclude, to exclude +a particular module version from use; and replace, to replace a module +version with a different module version. Exclude and replace apply only +in the main module's go.mod and are ignored in dependencies. +See https://research.swtch.com/vgo-mvs for details. + +The leading verb can be factored out of adjacent lines to create a block, +like in Go imports: + + require ( + new/thing v2.3.4 + old/thing v1.2.3 + ) + +The go.mod file is designed both to be edited directly and to be +easily updated by tools. The 'go mod edit' command can be used to +parse and edit the go.mod file from programs and tools. +See 'go help mod edit'. + +The go command automatically updates go.mod each time it uses the +module graph, to make sure go.mod always accurately reflects reality +and is properly formatted. For example, consider this go.mod file: + + module M + + require ( + A v1 + B v1.0.0 + C v1.0.0 + D v1.2.3 + E dev + ) + + exclude D v1.2.3 + +The update rewrites non-canonical version identifiers to semver form, +so A's v1 becomes v1.0.0 and E's dev becomes the pseudo-version for the +latest commit on the dev branch, perhaps v0.0.0-20180523231146-b3f5c0f6e5f1. + +The update modifies requirements to respect exclusions, so the +requirement on the excluded D v1.2.3 is updated to use the next +available version of D, perhaps D v1.2.4 or D v1.3.0. + +The update removes redundant or misleading requirements. +For example, if A v1.0.0 itself requires B v1.2.0 and C v1.0.0, +then go.mod's requirement of B v1.0.0 is misleading (superseded by +A's need for v1.2.0), and its requirement of C v1.0.0 is redundant +(implied by A's need for the same version), so both will be removed. +If module M contains packages that directly import packages from B or +C, then the requirements will be kept but updated to the actual +versions being used. + +Finally, the update reformats the go.mod in a canonical formatting, so +that future mechanical changes will result in minimal diffs. + +Because the module graph defines the meaning of import statements, any +commands that load packages also use and therefore update go.mod, +including go build, go get, go install, go list, go test, go mod graph, +go mod tidy, and go mod why. + `, +} diff --git a/libgo/go/cmd/go/internal/modload/import.go b/libgo/go/cmd/go/internal/modload/import.go new file mode 100644 index 00000000000..44c2a237267 --- /dev/null +++ b/libgo/go/cmd/go/internal/modload/import.go @@ -0,0 +1,228 @@ +// 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 modload + +import ( + "bytes" + "errors" + "fmt" + "go/build" + "internal/goroot" + "os" + "path/filepath" + "strings" + + "cmd/go/internal/cfg" + "cmd/go/internal/modfetch/codehost" + "cmd/go/internal/module" + "cmd/go/internal/par" + "cmd/go/internal/search" +) + +type ImportMissingError struct { + ImportPath string + Module module.Version +} + +func (e *ImportMissingError) Error() string { + if e.Module.Path == "" { + return "cannot find module providing package " + e.ImportPath + } + return "missing module for import: " + e.Module.Path + "@" + e.Module.Version + " provides " + e.ImportPath +} + +// Import finds the module and directory in the build list +// containing the package with the given import path. +// The answer must be unique: Import returns an error +// if multiple modules attempt to provide the same package. +// Import can return a module with an empty m.Path, for packages in the standard library. +// Import can return an empty directory string, for fake packages like "C" and "unsafe". +// +// If the package cannot be found in the current build list, +// Import returns an ImportMissingError as the error. +// If Import can identify a module that could be added to supply the package, +// the ImportMissingError records that module. +func Import(path string) (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". + return module.Version{}, "", nil + } + + // Is the package in the standard library? + if search.IsStandardImportPath(path) { + if strings.HasPrefix(path, "golang_org/") { + return module.Version{}, filepath.Join(cfg.GOROOT, "src/vendor", path), nil + } + if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) { + dir := filepath.Join(cfg.GOROOT, "src", path) + return module.Version{}, dir, nil + } + } + + // -mod=vendor is special. + // Everything must be in the main module or the main module's vendor directory. + if cfg.BuildMod == "vendor" { + mainDir, mainOK := dirInModule(path, Target.Path, ModRoot, true) + vendorDir, vendorOK := dirInModule(path, "", filepath.Join(ModRoot, "vendor"), false) + if mainOK && vendorOK { + return module.Version{}, "", fmt.Errorf("ambiguous import: found %s in multiple directories:\n\t%s\n\t%s", path, mainDir, vendorDir) + } + // Prefer to return main directory if there is one, + // Note that we're not checking that the package exists. + // We'll leave that for load. + if !vendorOK && mainDir != "" { + return Target, mainDir, nil + } + readVendorList() + return vendorMap[path], vendorDir, nil + } + + // Check each module on the build list. + var dirs []string + var mods []module.Version + for _, m := range buildList { + if !maybeInModule(path, m.Path) { + // Avoid possibly downloading irrelevant modules. + continue + } + root, isLocal, err := fetch(m) + if err != nil { + // 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 + } + dir, ok := dirInModule(path, m.Path, root, isLocal) + if ok { + mods = append(mods, m) + dirs = append(dirs, dir) + } + } + if len(mods) == 1 { + return mods[0], dirs[0], nil + } + if len(mods) > 0 { + var buf bytes.Buffer + fmt.Fprintf(&buf, "ambiguous import: found %s in multiple modules:", path) + for i, m := range mods { + fmt.Fprintf(&buf, "\n\t%s", m.Path) + if m.Version != "" { + fmt.Fprintf(&buf, " %s", m.Version) + } + fmt.Fprintf(&buf, " (%s)", dirs[i]) + } + return module.Version{}, "", errors.New(buf.String()) + } + + // Not on build list. + + // Look up module containing the package, for addition to the build list. + // Goal is to determine the module, download it to dir, and return m, dir, ErrMissing. + if cfg.BuildMod == "readonly" { + return module.Version{}, "", fmt.Errorf("import lookup disabled by -mod=%s", cfg.BuildMod) + } + + m, _, err = QueryPackage(path, "latest", Allowed) + if err != nil { + if _, ok := err.(*codehost.VCSError); ok { + return module.Version{}, "", err + } + return module.Version{}, "", &ImportMissingError{ImportPath: path} + } + return m, "", &ImportMissingError{ImportPath: path, Module: m} +} + +// maybeInModule reports whether, syntactically, +// a package with the given import path could be supplied +// by a module with the given module path (mpath). +func maybeInModule(path, mpath string) bool { + return mpath == path || + len(path) > len(mpath) && path[len(mpath)] == '/' && path[:len(mpath)] == mpath +} + +var haveGoModCache, haveGoFilesCache par.Cache + +// dirInModule locates the directory that would hold the package named by the given path, +// if it were in the module with module path mpath and root mdir. +// If path is syntactically not within mpath, +// or if mdir is a local file tree (isLocal == true) and the directory +// that would hold path is in a sub-module (covered by a go.mod below mdir), +// dirInModule returns "", false. +// +// Otherwise, dirInModule returns the name of the directory where +// Go source files would be expected, along with a boolean indicating +// whether there are in fact Go source files in that directory. +func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFiles bool) { + // Determine where to expect the package. + if path == mpath { + dir = mdir + } else if mpath == "" { // vendor directory + dir = filepath.Join(mdir, path) + } else if len(path) > len(mpath) && path[len(mpath)] == '/' && path[:len(mpath)] == mpath { + dir = filepath.Join(mdir, path[len(mpath)+1:]) + } else { + return "", false + } + + // Check that there aren't other modules in the way. + // This check is unnecessary inside the module cache + // and important to skip in the vendor directory, + // where all the module trees have been overlaid. + // So we only check local module trees + // (the main module, and any directory trees pointed at by replace directives). + if isLocal { + for d := dir; d != mdir && len(d) > len(mdir); { + haveGoMod := haveGoModCache.Do(d, func() interface{} { + _, err := os.Stat(filepath.Join(d, "go.mod")) + return err == nil + }).(bool) + + if haveGoMod { + return "", false + } + parent := filepath.Dir(d) + if parent == d { + // Break the loop, as otherwise we'd loop + // forever if d=="." and mdir=="". + break + } + d = parent + } + } + + // Now committed to returning dir (not ""). + + // Are there Go source files in the directory? + // We don't care about build tags, not even "+build ignore". + // We're just looking for a plausible directory. + haveGoFiles = haveGoFilesCache.Do(dir, func() interface{} { + f, err := os.Open(dir) + if err != nil { + return false + } + defer f.Close() + names, _ := f.Readdirnames(-1) + for _, name := range names { + if strings.HasSuffix(name, ".go") { + info, err := os.Stat(filepath.Join(dir, name)) + if err == nil && info.Mode().IsRegular() { + return true + } + } + } + return false + }).(bool) + + return dir, haveGoFiles +} diff --git a/libgo/go/cmd/go/internal/modload/import_test.go b/libgo/go/cmd/go/internal/modload/import_test.go new file mode 100644 index 00000000000..3f4ddab436c --- /dev/null +++ b/libgo/go/cmd/go/internal/modload/import_test.go @@ -0,0 +1,59 @@ +// 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 modload + +import ( + "internal/testenv" + "regexp" + "strings" + "testing" +) + +var importTests = []struct { + path string + err string +}{ + { + path: "golang.org/x/net/context", + err: "missing module for import: golang.org/x/net@.* provides golang.org/x/net/context", + }, + { + path: "golang.org/x/net", + err: "cannot find module providing package golang.org/x/net", + }, + { + path: "golang.org/x/text", + err: "missing module for import: golang.org/x/text@.* provides golang.org/x/text", + }, + { + path: "github.com/rsc/quote/buggy", + err: "missing module for import: github.com/rsc/quote@v1.5.2 provides github.com/rsc/quote/buggy", + }, + { + path: "github.com/rsc/quote", + err: "missing module for import: github.com/rsc/quote@v1.5.2 provides github.com/rsc/quote", + }, + { + path: "golang.org/x/foo/bar", + err: "cannot find module providing package golang.org/x/foo/bar", + }, +} + +func TestImport(t *testing.T) { + testenv.MustHaveExternalNetwork(t) + + for _, tt := range importTests { + t.Run(strings.Replace(tt.path, "/", "_", -1), func(t *testing.T) { + // Note that there is no build list, so Import should always fail. + m, dir, err := Import(tt.path) + if err == nil { + t.Fatalf("Import(%q) = %v, %v, nil; expected error", tt.path, m, dir) + } + if !regexp.MustCompile(tt.err).MatchString(err.Error()) { + t.Fatalf("Import(%q): error %q, want error matching %#q", tt.path, err, tt.err) + } + }) + } +} diff --git a/libgo/go/cmd/go/internal/modload/init.go b/libgo/go/cmd/go/internal/modload/init.go new file mode 100644 index 00000000000..f995bad13b5 --- /dev/null +++ b/libgo/go/cmd/go/internal/modload/init.go @@ -0,0 +1,600 @@ +// 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 modload + +import ( + "bytes" + "cmd/go/internal/base" + "cmd/go/internal/cache" + "cmd/go/internal/cfg" + "cmd/go/internal/load" + "cmd/go/internal/modconv" + "cmd/go/internal/modfetch" + "cmd/go/internal/modfetch/codehost" + "cmd/go/internal/modfile" + "cmd/go/internal/module" + "cmd/go/internal/mvs" + "cmd/go/internal/search" + "encoding/json" + "fmt" + "io/ioutil" + "os" + "path" + "path/filepath" + "regexp" + "strconv" + "strings" +) + +var ( + cwd string + MustUseModules = mustUseModules() + initialized bool + + ModRoot string + modFile *modfile.File + excluded map[module.Version]bool + Target module.Version + + gopath string + + CmdModInit bool // running 'go mod init' + CmdModModule string // module argument for 'go mod init' +) + +// ModFile returns the parsed go.mod file. +// +// Note that after calling ImportPaths or LoadBuildList, +// 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. +// To make permanent changes to the require statements +// in go.mod, edit it before calling ImportPaths or LoadBuildList. +func ModFile() *modfile.File { + return modFile +} + +func BinDir() string { + MustInit() + return filepath.Join(gopath, "bin") +} + +// mustUseModules reports whether we are invoked as vgo +// (as opposed to go). +// If so, we only support builds with go.mod files. +func mustUseModules() bool { + name := os.Args[0] + name = name[strings.LastIndex(name, "/")+1:] + name = name[strings.LastIndex(name, `\`)+1:] + return strings.HasPrefix(name, "vgo") +} + +var inGOPATH bool // running in GOPATH/src + +func Init() { + if initialized { + return + } + initialized = true + + env := os.Getenv("GO111MODULE") + switch env { + default: + base.Fatalf("go: unknown environment setting GO111MODULE=%s", env) + case "", "auto": + // leave MustUseModules alone + case "on": + MustUseModules = true + case "off": + if !MustUseModules { + return + } + } + + // Disable any prompting for passwords by Git. + // 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 + // prompting. + // See golang.org/issue/9341 and golang.org/issue/12706. + if os.Getenv("GIT_TERMINAL_PROMPT") == "" { + os.Setenv("GIT_TERMINAL_PROMPT", "0") + } + + // Disable any ssh connection pooling by Git. + // 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 + // until EOF to get all the data that the Git subprocess wrote before exiting. + // The EOF doesn't come until the child exits too, because the child + // is holding the write end of the pipe. + // This is unfortunate, but it has come up at least twice + // (see golang.org/issue/13453 and golang.org/issue/16104) + // and confuses users when it does. + // If the user has explicitly set GIT_SSH or GIT_SSH_COMMAND, + // 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") + } + + var err error + cwd, err = os.Getwd() + if err != nil { + base.Fatalf("go: %v", err) + } + + inGOPATH = false + for _, gopath := range filepath.SplitList(cfg.BuildContext.GOPATH) { + if gopath == "" { + continue + } + if search.InDir(cwd, filepath.Join(gopath, "src")) != "" { + inGOPATH = true + break + } + } + + if inGOPATH && !MustUseModules { + // No automatic enabling in GOPATH. + if root, _ := FindModuleRoot(cwd, "", false); root != "" { + cfg.GoModInGOPATH = filepath.Join(root, "go.mod") + } + return + } + + if CmdModInit { + // Running 'go mod init': go.mod will be created in current directory. + ModRoot = cwd + } else { + ModRoot, _ = FindModuleRoot(cwd, "", MustUseModules) + if !MustUseModules { + if ModRoot == "" { + return + } + if search.InDir(ModRoot, os.TempDir()) == "." { + // If you create /tmp/go.mod for experimenting, + // then any tests that create work directories under /tmp + // will find it and get modules when they're not expecting them. + // It's a bit of a peculiar thing to disallow but quite mysterious + // when it happens. See golang.org/issue/26708. + ModRoot = "" + fmt.Fprintf(os.Stderr, "go: warning: ignoring go.mod in system temp root %v\n", os.TempDir()) + return + } + } + } + + cfg.ModulesEnabled = true + load.ModBinDir = BinDir + load.ModLookup = Lookup + load.ModPackageModuleInfo = PackageModuleInfo + load.ModImportPaths = ImportPaths + load.ModPackageBuildInfo = PackageBuildInfo + load.ModInfoProg = ModInfoProg + load.ModImportFromFiles = ImportFromFiles + load.ModDirImportPath = DirImportPath + + search.SetModRoot(ModRoot) +} + +func init() { + load.ModInit = Init + + // Set modfetch.PkgMod unconditionally, so that go clean -modcache can run even without modules enabled. + if list := filepath.SplitList(cfg.BuildContext.GOPATH); len(list) > 0 && list[0] != "" { + modfetch.PkgMod = filepath.Join(list[0], "pkg/mod") + } +} + +// Enabled reports whether modules are (or must be) enabled. +// If modules must be enabled but are not, Enabled returns true +// and then the first use of module information will call die +// (usually through InitMod and MustInit). +func Enabled() bool { + if !initialized { + panic("go: Enabled called before Init") + } + return ModRoot != "" || MustUseModules +} + +// MustInit calls Init if needed and checks that +// modules are enabled and the main module has been found. +// If not, MustInit calls base.Fatalf with an appropriate message. +func MustInit() { + if Init(); ModRoot == "" { + die() + } + if c := cache.Default(); c == nil { + // With modules, there are no install locations for packages + // other than the build cache. + base.Fatalf("go: cannot use modules with build cache disabled") + } +} + +// Failed reports whether module loading failed. +// If Failed returns true, then any use of module information will call die. +func Failed() bool { + Init() + return cfg.ModulesEnabled && ModRoot == "" +} + +func die() { + if os.Getenv("GO111MODULE") == "off" { + base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'") + } + if inGOPATH && !MustUseModules { + base.Fatalf("go: modules disabled inside GOPATH/src by GO111MODULE=auto; see 'go help modules'") + } + base.Fatalf("go: cannot find main module; see 'go help modules'") +} + +func InitMod() { + MustInit() + if modFile != nil { + return + } + + list := filepath.SplitList(cfg.BuildContext.GOPATH) + if len(list) == 0 || list[0] == "" { + base.Fatalf("missing $GOPATH") + } + gopath = list[0] + if _, err := os.Stat(filepath.Join(gopath, "go.mod")); err == nil { + base.Fatalf("$GOPATH/go.mod exists but should not") + } + + oldSrcMod := filepath.Join(list[0], "src/mod") + pkgMod := filepath.Join(list[0], "pkg/mod") + infoOld, errOld := os.Stat(oldSrcMod) + _, errMod := os.Stat(pkgMod) + if errOld == nil && infoOld.IsDir() && errMod != nil && os.IsNotExist(errMod) { + os.Rename(oldSrcMod, pkgMod) + } + + modfetch.PkgMod = pkgMod + modfetch.GoSumFile = filepath.Join(ModRoot, "go.sum") + codehost.WorkRoot = filepath.Join(pkgMod, "cache/vcs") + + if CmdModInit { + // Running go mod init: do legacy module conversion + legacyModInit() + modFileToBuildList() + WriteGoMod() + return + } + + gomod := filepath.Join(ModRoot, "go.mod") + data, err := ioutil.ReadFile(gomod) + if err != nil { + if os.IsNotExist(err) { + legacyModInit() + modFileToBuildList() + WriteGoMod() + return + } + base.Fatalf("go: %v", err) + } + + f, err := modfile.Parse(gomod, data, fixVersion) + if err != nil { + // Errors returned by modfile.Parse begin with file:line. + base.Fatalf("go: errors parsing go.mod:\n%s\n", err) + } + modFile = f + + if len(f.Syntax.Stmt) == 0 || f.Module == nil { + // Empty mod file. Must add module path. + path, err := FindModulePath(ModRoot) + if err != nil { + base.Fatalf("go: %v", err) + } + f.AddModuleStmt(path) + } + + if len(f.Syntax.Stmt) == 1 && f.Module != nil { + // Entire file is just a module statement. + // Populate require if possible. + legacyModInit() + } + + excluded = make(map[module.Version]bool) + for _, x := range f.Exclude { + excluded[x.Mod] = true + } + modFileToBuildList() + WriteGoMod() +} + +// modFileToBuildList initializes buildList from the modFile. +func modFileToBuildList() { + Target = modFile.Module.Mod + list := []module.Version{Target} + for _, r := range modFile.Require { + list = append(list, r.Mod) + } + buildList = list +} + +// Allowed reports whether module m is allowed (not excluded) by the main module's go.mod. +func Allowed(m module.Version) bool { + return !excluded[m] +} + +func legacyModInit() { + if modFile == nil { + path, err := FindModulePath(ModRoot) + if err != nil { + base.Fatalf("go: %v", err) + } + fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", path) + modFile = new(modfile.File) + modFile.AddModuleStmt(path) + } + + for _, name := range altConfigs { + cfg := filepath.Join(ModRoot, name) + data, err := ioutil.ReadFile(cfg) + if err == nil { + convert := modconv.Converters[name] + if convert == nil { + return + } + fmt.Fprintf(os.Stderr, "go: copying requirements from %s\n", base.ShortPath(cfg)) + cfg = filepath.ToSlash(cfg) + if err := modconv.ConvertLegacyConfig(modFile, cfg, data); err != nil { + base.Fatalf("go: %v", err) + } + if len(modFile.Syntax.Stmt) == 1 { + // Add comment to avoid re-converting every time it runs. + modFile.AddComment("// go: no requirements found in " + name) + } + return + } + } +} + +var altConfigs = []string{ + "Gopkg.lock", + + "GLOCKFILE", + "Godeps/Godeps.json", + "dependencies.tsv", + "glide.lock", + "vendor.conf", + "vendor.yml", + "vendor/manifest", + "vendor/vendor.json", + + ".git/config", +} + +// Exported only for testing. +func FindModuleRoot(dir, limit string, legacyConfigOK bool) (root, file string) { + dir = filepath.Clean(dir) + dir1 := dir + limit = filepath.Clean(limit) + + // Look for enclosing go.mod. + for { + if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { + return dir, "go.mod" + } + if dir == limit { + break + } + d := filepath.Dir(dir) + if d == dir { + break + } + dir = d + } + + // Failing that, look for enclosing alternate version config. + if legacyConfigOK { + dir = dir1 + for { + for _, name := range altConfigs { + if _, err := os.Stat(filepath.Join(dir, name)); err == nil { + return dir, name + } + } + if dir == limit { + break + } + d := filepath.Dir(dir) + if d == dir { + break + } + dir = d + } + } + + return "", "" +} + +// Exported only for testing. +func FindModulePath(dir string) (string, error) { + if CmdModModule != "" { + // Running go mod init x/y/z; return x/y/z. + return CmdModModule, nil + } + + // Cast about for import comments, + // first in top-level directory, then in subdirectories. + list, _ := ioutil.ReadDir(dir) + for _, info := range list { + if info.Mode().IsRegular() && strings.HasSuffix(info.Name(), ".go") { + if com := findImportComment(filepath.Join(dir, info.Name())); com != "" { + return com, nil + } + } + } + for _, info1 := range list { + if info1.IsDir() { + files, _ := ioutil.ReadDir(filepath.Join(dir, info1.Name())) + for _, info2 := range files { + if info2.Mode().IsRegular() && strings.HasSuffix(info2.Name(), ".go") { + if com := findImportComment(filepath.Join(dir, info1.Name(), info2.Name())); com != "" { + return path.Dir(com), nil + } + } + } + } + } + + // Look for Godeps.json declaring import path. + data, _ := ioutil.ReadFile(filepath.Join(dir, "Godeps/Godeps.json")) + var cfg1 struct{ ImportPath string } + json.Unmarshal(data, &cfg1) + if cfg1.ImportPath != "" { + return cfg1.ImportPath, nil + } + + // Look for vendor.json declaring import path. + data, _ = ioutil.ReadFile(filepath.Join(dir, "vendor/vendor.json")) + var cfg2 struct{ RootPath string } + json.Unmarshal(data, &cfg2) + if cfg2.RootPath != "" { + return cfg2.RootPath, nil + } + + // Look for path in GOPATH. + for _, gpdir := range filepath.SplitList(cfg.BuildContext.GOPATH) { + if gpdir == "" { + continue + } + if rel := search.InDir(dir, filepath.Join(gpdir, "src")); rel != "" && rel != "." { + return filepath.ToSlash(rel), nil + } + } + + // Look for .git/config with github origin as last resort. + data, _ = ioutil.ReadFile(filepath.Join(dir, ".git/config")) + if m := gitOriginRE.FindSubmatch(data); m != nil { + return "github.com/" + string(m[1]), nil + } + + return "", fmt.Errorf("cannot determine module path for source directory %s (outside GOPATH, no import comments)", dir) +} + +var ( + gitOriginRE = regexp.MustCompile(`(?m)^\[remote "origin"\]\r?\n\turl = (?:https://github.com/|git@github.com:|gh:)([^/]+/[^/]+?)(\.git)?\r?\n`) + importCommentRE = regexp.MustCompile(`(?m)^package[ \t]+[^ \t\r\n/]+[ \t]+//[ \t]+import[ \t]+(\"[^"]+\")[ \t]*\r?\n`) +) + +func findImportComment(file string) string { + data, err := ioutil.ReadFile(file) + if err != nil { + return "" + } + m := importCommentRE.FindSubmatch(data) + if m == nil { + return "" + } + path, err := strconv.Unquote(string(m[1])) + if err != nil { + return "" + } + return path +} + +var allowWriteGoMod = true + +// DisallowWriteGoMod causes future calls to WriteGoMod to do nothing at all. +func DisallowWriteGoMod() { + allowWriteGoMod = false +} + +// AllowWriteGoMod undoes the effect of DisallowWriteGoMod: +// future calls to WriteGoMod will update go.mod if needed. +// Note that any past calls have been discarded, so typically +// a call to AlowWriteGoMod should be followed by a call to WriteGoMod. +func AllowWriteGoMod() { + allowWriteGoMod = true +} + +// MinReqs returns a Reqs with minimal dependencies of Target, +// as will be written to go.mod. +func MinReqs() mvs.Reqs { + var direct []string + for _, m := range buildList[1:] { + if loaded.direct[m.Path] { + direct = append(direct, m.Path) + } + } + min, err := mvs.Req(Target, buildList, direct, Reqs()) + if err != nil { + base.Fatalf("go: %v", err) + } + return &mvsReqs{buildList: append([]module.Version{Target}, min...)} +} + +// 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" { + return + } + + 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], + }) + } + modFile.SetRequire(list) + } + + file := filepath.Join(ModRoot, "go.mod") + old, _ := ioutil.ReadFile(file) + modFile.Cleanup() // clean file after edits + new, err := modFile.Format() + if err != nil { + base.Fatalf("go: %v", err) + } + if !bytes.Equal(old, new) { + if cfg.BuildMod == "readonly" { + base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly") + } + if err := ioutil.WriteFile(file, new, 0666); err != nil { + base.Fatalf("go: %v", err) + } + } + modfetch.WriteGoSum() +} + +func fixVersion(path, vers string) (string, error) { + // Special case: remove the old -gopkgin- hack. + if strings.HasPrefix(path, "gopkg.in/") && strings.Contains(vers, "-gopkgin-") { + vers = vers[strings.Index(vers, "-gopkgin-")+len("-gopkgin-"):] + } + + // fixVersion is called speculatively on every + // module, version pair from every go.mod file. + // Avoid the query if it looks OK. + _, pathMajor, ok := module.SplitPathVersion(path) + if !ok { + return "", fmt.Errorf("malformed module path: %s", path) + } + if vers != "" && module.CanonicalVersion(vers) == vers && module.MatchPathMajor(vers, pathMajor) { + return vers, nil + } + + info, err := Query(path, vers, nil) + if err != nil { + return "", err + } + return info.Version, nil +} diff --git a/libgo/go/cmd/go/internal/modload/list.go b/libgo/go/cmd/go/internal/modload/list.go new file mode 100644 index 00000000000..69a832de1df --- /dev/null +++ b/libgo/go/cmd/go/internal/modload/list.go @@ -0,0 +1,109 @@ +// 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 modload + +import ( + "fmt" + "os" + "strings" + + "cmd/go/internal/base" + "cmd/go/internal/modinfo" + "cmd/go/internal/module" + "cmd/go/internal/par" + "cmd/go/internal/search" +) + +func ListModules(args []string, listU, listVersions bool) []*modinfo.ModulePublic { + mods := listModules(args) + if listU || listVersions { + var work par.Work + for _, m := range mods { + work.Add(m) + if m.Replace != nil { + work.Add(m.Replace) + } + } + work.Do(10, func(item interface{}) { + m := item.(*modinfo.ModulePublic) + if listU { + addUpdate(m) + } + if listVersions { + addVersions(m) + } + }) + } + return mods +} + +func listModules(args []string) []*modinfo.ModulePublic { + LoadBuildList() + if len(args) == 0 { + return []*modinfo.ModulePublic{moduleInfo(buildList[0], true)} + } + + var mods []*modinfo.ModulePublic + matchedBuildList := make([]bool, len(buildList)) + for _, arg := range args { + if strings.Contains(arg, `\`) { + base.Fatalf("go: module paths never use backslash") + } + if search.IsRelativePath(arg) { + base.Fatalf("go: cannot use relative path %s to specify module", arg) + } + if i := strings.Index(arg, "@"); i >= 0 { + info, err := Query(arg[:i], arg[i+1:], nil) + if err != nil { + mods = append(mods, &modinfo.ModulePublic{ + Path: arg[:i], + Version: arg[i+1:], + Error: &modinfo.ModuleError{ + Err: err.Error(), + }, + }) + continue + } + mods = append(mods, moduleInfo(module.Version{Path: arg[:i], Version: info.Version}, false)) + 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 match(m.Path) { + matched = true + if !matchedBuildList[i] { + matchedBuildList[i] = true + mods = append(mods, moduleInfo(m, true)) + } + } + } + if !matched { + if literal { + mods = append(mods, &modinfo.ModulePublic{ + Path: arg, + Error: &modinfo.ModuleError{ + Err: fmt.Sprintf("module %q is not a known dependency", arg), + }, + }) + } else { + fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg) + } + } + } + + return mods +} diff --git a/libgo/go/cmd/go/internal/modload/load.go b/libgo/go/cmd/go/internal/modload/load.go new file mode 100644 index 00000000000..5bf6c9b1cf9 --- /dev/null +++ b/libgo/go/cmd/go/internal/modload/load.go @@ -0,0 +1,1071 @@ +// 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 modload + +import ( + "bytes" + "errors" + "fmt" + "go/build" + "io/ioutil" + "os" + "path" + "path/filepath" + "sort" + "strings" + "sync" + + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "cmd/go/internal/imports" + "cmd/go/internal/modfetch" + "cmd/go/internal/modfile" + "cmd/go/internal/module" + "cmd/go/internal/mvs" + "cmd/go/internal/par" + "cmd/go/internal/search" + "cmd/go/internal/semver" + "cmd/go/internal/str" +) + +// buildList is the list of modules to use for building packages. +// It is initialized by calling ImportPaths, ImportFromFiles, +// LoadALL, or LoadBuildList, 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 + +// loaded is the most recently-used package loader. +// It holds details about individual packages. +// +// Note that loaded.buildList is only valid during a load operation; +// afterward, it is copied back into the global buildList, +// which should be used instead. +var loaded *loader + +// ImportPaths returns the set of packages matching the args (patterns), +// adding modules to the build list as needed to satisfy new imports. +func ImportPaths(patterns []string) []*search.Match { + InitMod() + + var matches []*search.Match + for _, pattern := range search.CleanPatterns(patterns) { + m := &search.Match{ + Pattern: pattern, + Literal: !strings.Contains(pattern, "...") && !search.IsMetaPackage(pattern), + } + if m.Literal { + m.Pkgs = []string{pattern} + } + matches = append(matches, m) + } + + fsDirs := make([][]string, len(matches)) + loaded = newLoader() + updateMatches := func(iterating bool) { + for i, m := range matches { + switch { + case build.IsLocalImport(m.Pattern) || filepath.IsAbs(m.Pattern): + // Evaluate list of file system directories on first iteration. + if fsDirs[i] == nil { + var dirs []string + if m.Literal { + dirs = []string{m.Pattern} + } else { + dirs = search.MatchPackagesInFS(m.Pattern).Pkgs + } + fsDirs[i] = dirs + } + + // Make a copy of the directory list and translate to import paths. + // Note that whether a directory corresponds to an import path + // changes as the build list is updated, and a directory can change + // from not being in the build list to being in it and back as + // the exact version of a particular module increases during + // the loader iterations. + m.Pkgs = str.StringList(fsDirs[i]) + for i, pkg := range m.Pkgs { + dir := pkg + if !filepath.IsAbs(dir) { + dir = filepath.Join(cwd, pkg) + } else { + dir = filepath.Clean(dir) + } + + // Note: The checks for @ here are just to avoid misinterpreting + // the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar). + // It's not strictly necessary but helpful to keep the checks. + if dir == ModRoot { + pkg = Target.Path + } else if strings.HasPrefix(dir, ModRoot+string(filepath.Separator)) && !strings.Contains(dir[len(ModRoot):], "@") { + suffix := filepath.ToSlash(dir[len(ModRoot):]) + if strings.HasPrefix(suffix, "/vendor/") { + // TODO getmode vendor check + pkg = strings.TrimPrefix(suffix, "/vendor/") + } else { + pkg = Target.Path + suffix + } + } else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && !strings.Contains(sub, "@") { + pkg = filepath.ToSlash(sub) + } else if path := pathInModuleCache(dir); path != "" { + pkg = path + } else { + pkg = "" + if !iterating { + base.Errorf("go: directory %s outside available modules", base.ShortPath(dir)) + } + } + info, err := os.Stat(dir) + if err != nil || !info.IsDir() { + // If the directory does not exist, + // don't turn it into an import path + // that will trigger a lookup. + pkg = "" + if !iterating { + if err != nil { + base.Errorf("go: no such directory %v", m.Pattern) + } else { + base.Errorf("go: %s is not a directory", m.Pattern) + } + } + } + m.Pkgs[i] = pkg + } + + case strings.Contains(m.Pattern, "..."): + m.Pkgs = matchPackages(m.Pattern, loaded.tags, true, buildList) + + case m.Pattern == "all": + loaded.testAll = true + if iterating { + // Enumerate the packages in the main module. + // We'll load the dependencies as we find them. + m.Pkgs = matchPackages("...", loaded.tags, false, []module.Version{Target}) + } else { + // Starting with the packages in the main module, + // enumerate the full list of "all". + m.Pkgs = loaded.computePatternAll(m.Pkgs) + } + + case search.IsMetaPackage(m.Pattern): // std, cmd + if len(m.Pkgs) == 0 { + m.Pkgs = search.MatchPackages(m.Pattern).Pkgs + } + } + } + } + + loaded.load(func() []string { + var roots []string + updateMatches(true) + for _, m := range matches { + for _, pkg := range m.Pkgs { + if pkg != "" { + roots = append(roots, pkg) + } + } + } + return roots + }) + + // One last pass to finalize wildcards. + updateMatches(false) + + // A given module path may be used as itself or as a replacement for another + // module, but not both at the same time. Otherwise, the aliasing behavior is + // too subtle (see https://golang.org/issue/26607), and we don't want to + // commit to a specific behavior at this point. + firstPath := make(map[module.Version]string, len(buildList)) + for _, mod := range buildList { + src := mod + if rep := Replacement(mod); rep.Path != "" { + src = rep + } + 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) + } + } + base.ExitIfErrors() + WriteGoMod() + + search.WarnUnmatched(matches) + return matches +} + +// 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 { + for _, m := range buildList[1:] { + root, err := modfetch.DownloadDir(m) + if err != nil { + continue + } + if sub := search.InDir(dir, root); sub != "" { + sub = filepath.ToSlash(sub) + if !strings.Contains(sub, "/vendor/") && !strings.HasPrefix(sub, "vendor/") && !strings.Contains(sub, "@") { + return path.Join(m.Path, filepath.ToSlash(sub)) + } + } + } + return "" +} + +// warnPattern returns list, the result of matching pattern, +// but if list is empty then first it prints a warning about +// the pattern not matching any packages. +func warnPattern(pattern string, list []string) []string { + if len(list) == 0 { + fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) + } + return list +} + +// ImportFromFiles adds modules to the build list as needed +// to satisfy the imports in the named Go source files. +func ImportFromFiles(gofiles []string) { + InitMod() + + imports, testImports, err := imports.ScanFiles(gofiles, imports.Tags()) + if err != nil { + base.Fatalf("go: %v", err) + } + + loaded = newLoader() + loaded.load(func() []string { + var roots []string + roots = append(roots, imports...) + roots = append(roots, testImports...) + return roots + }) + WriteGoMod() +} + +// DirImportPath returns the effective import path for dir, +// provided it is within the main module, or else returns ".". +func DirImportPath(dir string) string { + if !filepath.IsAbs(dir) { + dir = filepath.Join(cwd, dir) + } else { + dir = filepath.Clean(dir) + } + + if dir == ModRoot { + return Target.Path + } + if strings.HasPrefix(dir, ModRoot+string(filepath.Separator)) { + suffix := filepath.ToSlash(dir[len(ModRoot):]) + if strings.HasPrefix(suffix, "/vendor/") { + return strings.TrimPrefix(suffix, "/vendor/") + } + return Target.Path + suffix + } + return "." +} + +// LoadBuildList loads and returns the build list from go.mod. +// The loading of the build list happens automatically in ImportPaths: +// LoadBuildList need only be called if ImportPaths is not +// (typically in commands that care about the module but +// no particular package). +func LoadBuildList() []module.Version { + InitMod() + ReloadBuildList() + WriteGoMod() + return buildList +} + +func ReloadBuildList() []module.Version { + loaded = newLoader() + loaded.load(func() []string { return nil }) + return buildList +} + +// LoadALL returns the set of all packages in the current module +// and their dependencies in any other modules, without filtering +// due to build tags, except "+build ignore". +// It adds modules to the build list as needed to satisfy new imports. +// This set is useful for deciding whether a particular import is needed +// anywhere in a module. +func LoadALL() []string { + return loadAll(true) +} + +// LoadVendor is like LoadALL but only follows test dependencies +// for tests in the main module. Tests in dependency modules are +// ignored completely. +// This set is useful for identifying the which packages to include in a vendor directory. +func LoadVendor() []string { + return loadAll(false) +} + +func loadAll(testAll bool) []string { + InitMod() + + loaded = newLoader() + loaded.isALL = true + loaded.tags = anyTags + loaded.testAll = testAll + if !testAll { + loaded.testRoots = true + } + all := TargetPackages() + loaded.load(func() []string { return all }) + WriteGoMod() + + var paths []string + for _, pkg := range loaded.pkgs { + if e, ok := pkg.err.(*ImportMissingError); ok && e.Module.Path == "" { + continue // Package doesn't actually exist. + } + paths = append(paths, pkg.path) + } + return paths +} + +// anyTags is a special tags map that satisfies nearly all build tag expressions. +// Only "ignore" and malformed build tag requirements are considered false. +var anyTags = map[string]bool{"*": true} + +// TargetPackages returns the list of packages in the target (top-level) module, +// under all build tag settings. +func TargetPackages() []string { + return matchPackages("...", anyTags, false, []module.Version{Target}) +} + +// BuildList returns the module build list, +// typically constructed by a previous call to +// LoadBuildList or ImportPaths. +// The caller must not modify the returned list. +func BuildList() []module.Version { + return buildList +} + +// SetBuildList sets the module build list. +// The caller is responsible for ensuring that the list is valid. +// SetBuildList does not retain a reference to the original list. +func SetBuildList(list []module.Version) { + buildList = append([]module.Version{}, list...) +} + +// 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 +// for the packages that have been loaded, ImportMap returns the empty string. +func ImportMap(path string) string { + pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) + if !ok { + return "" + } + return pkg.path +} + +// PackageDir returns the directory containing the source code +// for the package named by the import path. +func PackageDir(path string) string { + pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) + if !ok { + return "" + } + return pkg.dir +} + +// PackageModule returns the module providing the package named by the import path. +func PackageModule(path string) module.Version { + pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) + if !ok { + return module.Version{} + } + return pkg.mod +} + +// ModuleUsedDirectly reports whether the main module directly imports +// some package in the module with the given path. +func ModuleUsedDirectly(path string) bool { + return loaded.direct[path] +} + +// Lookup returns the source directory, import path, and any loading error for +// the package at path. +// Lookup requires that one of the Load functions in this package has already +// been called. +func Lookup(path string) (dir, realPath string, err error) { + pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) + if !ok { + // The loader should have found all the relevant paths. + // There are a few exceptions, though: + // - during go list without -test, the p.Resolve calls to process p.TestImports and p.XTestImports + // end up here to canonicalize the import paths. + // - during any load, non-loaded packages like "unsafe" end up here. + // - during any load, build-injected dependencies like "runtime/cgo" end up here. + // - because we ignore appengine/* in the module loader, + // the dependencies of any actual appengine/* library end up here. + dir := findStandardImportPath(path) + if dir != "" { + return dir, path, nil + } + return "", "", errMissing + } + return pkg.dir, pkg.path, pkg.err +} + +// A loader manages the process of loading information about +// the required packages for a particular build, +// checking that the packages are available in the module set, +// and updating the module set if needed. +// Loading is an iterative process: try to load all the needed packages, +// but if imports are missing, try to resolve those imports, and repeat. +// +// Although most of the loading state is maintained in the loader struct, +// one key piece - the build list - is a global, so that it can be modified +// separate from the loading operation, such as during "go get" +// upgrades/downgrades or in "go mod" operations. +// TODO(rsc): It might be nice to make the loader take and return +// a buildList rather than hard-coding use of the global. +type loader struct { + tags map[string]bool // tags for scanDir + testRoots bool // include tests for roots + isALL bool // created with LoadALL + testAll bool // include tests for all packages + + // reset on each iteration + roots []*loadPkg + pkgs []*loadPkg + work *par.Work // current work queue + pkgCache *par.Cache // map from string to *loadPkg + + // computed at end of iterations + direct map[string]bool // imported directly by main module + goVersion map[string]string // go version recorded in each module +} + +// LoadTests controls whether the loaders load tests of the root packages. +var LoadTests bool + +func newLoader() *loader { + ld := new(loader) + ld.tags = imports.Tags() + ld.testRoots = LoadTests + return ld +} + +func (ld *loader) reset() { + ld.roots = nil + ld.pkgs = nil + ld.work = new(par.Work) + ld.pkgCache = new(par.Cache) +} + +// A loadPkg records information about a single loaded package. +type loadPkg struct { + path string // import path + mod module.Version // module providing package + dir string // directory containing source code + imports []*loadPkg // packages imported by this one + err error // error loading package + stack *loadPkg // package importing this one in minimal import stack for this pkg + test *loadPkg // package with test imports, if we need test + testOf *loadPkg + testImports []string // test-only imports, saved for use by pkg.test. +} + +var errMissing = errors.New("cannot find package") + +// load attempts to load the build graph needed to process a set of root packages. +// The set of root packages is defined by the addRoots function, +// which must call add(path) with the import path of each root package. +func (ld *loader) load(roots func() []string) { + var err error + reqs := Reqs() + buildList, err = mvs.BuildList(Target, reqs) + if err != nil { + base.Fatalf("go: %v", err) + } + + added := make(map[string]bool) + for { + ld.reset() + if roots != nil { + // Note: the returned roots can change on each iteration, + // since the expansion of package patterns depends on the + // build list we're using. + for _, path := range roots() { + ld.work.Add(ld.pkg(path, true)) + } + } + ld.work.Do(10, ld.doPkg) + ld.buildStacks() + numAdded := 0 + haveMod := make(map[module.Version]bool) + for _, m := range buildList { + haveMod[m] = true + } + for _, pkg := range ld.pkgs { + if err, ok := pkg.err.(*ImportMissingError); ok && err.Module.Path != "" { + if added[pkg.path] { + base.Fatalf("go: %s: looping trying to add package", pkg.stackText()) + } + added[pkg.path] = true + numAdded++ + if !haveMod[err.Module] { + haveMod[err.Module] = true + buildList = append(buildList, err.Module) + } + continue + } + // Leave other errors for Import or load.Packages to report. + } + base.ExitIfErrors() + if numAdded == 0 { + break + } + + // Recompute buildList with all our additions. + reqs = Reqs() + buildList, err = mvs.BuildList(Target, reqs) + if err != nil { + base.Fatalf("go: %v", err) + } + } + base.ExitIfErrors() + + // 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 != "" { + ld.direct[dep.mod.Path] = true + } + } + } + } + + // Add Go versions, computed during walk. + ld.goVersion = make(map[string]string) + for _, m := range buildList { + v, _ := reqs.(*mvsReqs).versions.Load(m) + ld.goVersion[m.Path], _ = v.(string) + } + + // Mix in direct markings (really, lack of indirect markings) + // from go.mod, unless we scanned the whole module + // and can therefore be sure we know better than go.mod. + if !ld.isALL && modFile != nil { + for _, r := range modFile.Require { + if !r.Indirect { + ld.direct[r.Mod.Path] = true + } + } + } +} + +// pkg returns the *loadPkg for path, creating and queuing it if needed. +// If the package should be tested, its test is created but not queued +// (the test is queued after processing pkg). +// If isRoot is true, the pkg is being queued as one of the roots of the work graph. +func (ld *loader) pkg(path string, isRoot bool) *loadPkg { + return ld.pkgCache.Do(path, func() interface{} { + pkg := &loadPkg{ + path: path, + } + if ld.testRoots && isRoot || ld.testAll { + test := &loadPkg{ + path: path, + testOf: pkg, + } + pkg.test = test + } + if isRoot { + ld.roots = append(ld.roots, pkg) + } + ld.work.Add(pkg) + return pkg + }).(*loadPkg) +} + +// doPkg processes a package on the work queue. +func (ld *loader) doPkg(item interface{}) { + // TODO: what about replacements? + pkg := item.(*loadPkg) + var imports []string + if pkg.testOf != nil { + pkg.dir = pkg.testOf.dir + pkg.mod = pkg.testOf.mod + imports = pkg.testOf.testImports + } else { + if strings.Contains(pkg.path, "@") { + // Leave for error during load. + return + } + if build.IsLocalImport(pkg.path) { + // Leave for error during load. + // (Module mode does not allow local imports.) + return + } + + pkg.mod, pkg.dir, pkg.err = Import(pkg.path) + if pkg.dir == "" { + return + } + if cfg.BuildContext.Compiler == "gccgo" && pkg.mod.Path == "" { + return + } + + var testImports []string + var err error + imports, testImports, err = scanDir(pkg.dir, ld.tags) + if err != nil { + pkg.err = err + return + } + if pkg.test != nil { + pkg.testImports = testImports + } + } + + for _, path := range imports { + pkg.imports = append(pkg.imports, ld.pkg(path, false)) + } + + // Now that pkg.dir, pkg.mod, pkg.testImports are set, we can queue pkg.test. + // TODO: All that's left is creating new imports. Why not just do it now? + if pkg.test != nil { + ld.work.Add(pkg.test) + } +} + +// computePatternAll returns the list of packages matching pattern "all", +// starting with a list of the import paths for the packages in the main module. +func (ld *loader) computePatternAll(paths []string) []string { + seen := make(map[*loadPkg]bool) + var all []string + var walk func(*loadPkg) + walk = func(pkg *loadPkg) { + if seen[pkg] { + return + } + seen[pkg] = true + if pkg.testOf == nil { + all = append(all, pkg.path) + } + for _, p := range pkg.imports { + walk(p) + } + if p := pkg.test; p != nil { + walk(p) + } + } + for _, path := range paths { + walk(ld.pkg(path, false)) + } + sort.Strings(all) + + return all +} + +// 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. +// +// The standard magic import is "C", for cgo. +// +// The only other known magic imports are appengine and appengine/*. +// These are so old that they predate "go get" and did not use URL-like paths. +// Most code today now uses google.golang.org/appengine instead, +// but not all code has been so updated. When we mostly ignore build tags +// during "go vendor", we look into "// +build appengine" files and +// may see these legacy imports. We drop them so that the module +// search does not look for modules to try to satisfy them. +func scanDir(dir string, tags map[string]bool) (imports_, testImports []string, err error) { + imports_, testImports, err = imports.ScanDir(dir, tags) + + filter := func(x []string) []string { + w := 0 + for _, pkg := range x { + if pkg != "C" && pkg != "appengine" && !strings.HasPrefix(pkg, "appengine/") && + pkg != "appengine_internal" && !strings.HasPrefix(pkg, "appengine_internal/") { + x[w] = pkg + w++ + } + } + return x[:w] + } + + return filter(imports_), filter(testImports), err +} + +// buildStacks computes minimal import stacks for each package, +// for use in error messages. When it completes, packages that +// are part of the original root set have pkg.stack == nil, +// and other packages have pkg.stack pointing at the next +// package up the import stack in their minimal chain. +// As a side effect, buildStacks also constructs ld.pkgs, +// the list of all packages loaded. +func (ld *loader) buildStacks() { + if len(ld.pkgs) > 0 { + panic("buildStacks") + } + for _, pkg := range ld.roots { + pkg.stack = pkg // sentinel to avoid processing in next loop + ld.pkgs = append(ld.pkgs, pkg) + } + for i := 0; i < len(ld.pkgs); i++ { // not range: appending to ld.pkgs in loop + pkg := ld.pkgs[i] + for _, next := range pkg.imports { + if next.stack == nil { + next.stack = pkg + ld.pkgs = append(ld.pkgs, next) + } + } + if next := pkg.test; next != nil && next.stack == nil { + next.stack = pkg + ld.pkgs = append(ld.pkgs, next) + } + } + for _, pkg := range ld.roots { + pkg.stack = nil + } +} + +// stackText builds the import stack text to use when +// reporting an error in pkg. It has the general form +// +// import root -> +// import other -> +// import other2 -> +// import pkg +// +func (pkg *loadPkg) stackText() string { + var stack []*loadPkg + for p := pkg.stack; p != nil; p = p.stack { + stack = append(stack, p) + } + + var buf bytes.Buffer + for i := len(stack) - 1; i >= 0; i-- { + p := stack[i] + if p.testOf != nil { + fmt.Fprintf(&buf, "test ->\n\t") + } else { + fmt.Fprintf(&buf, "import %q ->\n\t", p.path) + } + } + fmt.Fprintf(&buf, "import %q", pkg.path) + return buf.String() +} + +// why returns the text to use in "go mod why" output about the given package. +// It is less ornate than the stackText but conatins the same information. +func (pkg *loadPkg) why() string { + var buf strings.Builder + var stack []*loadPkg + for p := pkg; p != nil; p = p.stack { + stack = append(stack, p) + } + + for i := len(stack) - 1; i >= 0; i-- { + p := stack[i] + if p.testOf != nil { + fmt.Fprintf(&buf, "%s.test\n", p.testOf.path) + } else { + fmt.Fprintf(&buf, "%s\n", p.path) + } + } + return buf.String() +} + +// Why returns the "go mod why" output stanza for the given package, +// without the leading # comment. +// The package graph must have been loaded already, usually by LoadALL. +// If there is no reason for the package to be in the current build, +// Why returns an empty string. +func Why(path string) string { + pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) + if !ok { + return "" + } + return pkg.why() +} + +// WhyDepth returns the number of steps in the Why listing. +// If there is no reason for the package to be in the current build, +// WhyDepth returns 0. +func WhyDepth(path string) int { + n := 0 + pkg, _ := loaded.pkgCache.Get(path).(*loadPkg) + for p := pkg; p != nil; p = p.stack { + n++ + } + return n +} + +// Replacement returns the replacement for mod, if any, from go.mod. +// If there is no replacement for mod, Replacement returns +// a module.Version with Path == "". +func Replacement(mod module.Version) module.Version { + if modFile == nil { + // Happens during testing. + return module.Version{} + } + + var found *modfile.Replace + for _, r := range modFile.Replace { + if r.Old.Path == mod.Path && (r.Old.Version == "" || r.Old.Version == mod.Version) { + found = r // keep going + } + } + if found == nil { + return module.Version{} + } + return found.New +} + +// mvsReqs implements mvs.Reqs for module semantic versions, +// with any exclusions or replacements applied internally. +type mvsReqs struct { + buildList []module.Version + cache par.Cache + versions sync.Map +} + +// Reqs returns the current module requirement graph. +// Future calls to SetBuildList do not affect the operation +// of the returned Reqs. +func Reqs() mvs.Reqs { + r := &mvsReqs{ + buildList: buildList, + } + return r +} + +func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { + type cached struct { + list []module.Version + err error + } + + c := r.cache.Do(mod, func() interface{} { + list, err := r.required(mod) + if err != nil { + return cached{nil, err} + } + for i, mv := range list { + for excluded[mv] { + mv1, err := r.next(mv) + if err != nil { + return cached{nil, err} + } + if mv1.Version == "none" { + return cached{nil, fmt.Errorf("%s(%s) depends on excluded %s(%s) with no newer version available", mod.Path, mod.Version, mv.Path, mv.Version)} + } + mv = mv1 + } + list[i] = mv + } + + return cached{list, nil} + }).(cached) + + return c.list, c.err +} + +var vendorOnce sync.Once + +var ( + vendorList []module.Version + vendorMap map[string]module.Version +) + +// readVendorList reads the list of vendored modules from vendor/modules.txt. +func readVendorList() { + vendorOnce.Do(func() { + vendorList = nil + vendorMap = make(map[string]module.Version) + data, _ := ioutil.ReadFile(filepath.Join(ModRoot, "vendor/modules.txt")) + var m module.Version + for _, line := range strings.Split(string(data), "\n") { + if strings.HasPrefix(line, "# ") { + f := strings.Fields(line) + m = module.Version{} + if len(f) == 3 && semver.IsValid(f[2]) { + m = module.Version{Path: f[1], Version: f[2]} + vendorList = append(vendorList, m) + } + } else if m.Path != "" { + f := strings.Fields(line) + if len(f) == 1 { + vendorMap[f[0]] = m + } + } + } + }) +} + +func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version { + var list []module.Version + for _, r := range f.Require { + list = append(list, r.Mod) + } + return list +} + +func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) { + if mod == Target { + if modFile.Go != nil { + r.versions.LoadOrStore(mod, modFile.Go.Version) + } + var list []module.Version + return append(list, r.buildList[1:]...), nil + } + + if cfg.BuildMod == "vendor" { + // For every module other than the target, + // return the full list of modules from modules.txt. + readVendorList() + return vendorList, nil + } + + origPath := mod.Path + if repl := Replacement(mod); repl.Path != "" { + if repl.Version == "" { + // TODO: need to slip the new version into the tags list etc. + dir := repl.Path + if !filepath.IsAbs(dir) { + dir = filepath.Join(ModRoot, dir) + } + gomod := filepath.Join(dir, "go.mod") + data, err := ioutil.ReadFile(gomod) + if err != nil { + base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err) + return nil, ErrRequire + } + f, err := modfile.ParseLax(gomod, data, nil) + if err != nil { + base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err) + return nil, ErrRequire + } + if f.Go != nil { + r.versions.LoadOrStore(mod, f.Go.Version) + } + return r.modFileToList(f), nil + } + mod = repl + } + + if mod.Version == "none" { + return nil, nil + } + + if !semver.IsValid(mod.Version) { + // Disallow the broader queries supported by fetch.Lookup. + base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", mod.Path, mod.Version) + } + + data, err := modfetch.GoMod(mod.Path, mod.Version) + if err != nil { + base.Errorf("go: %s@%s: %v\n", mod.Path, mod.Version, err) + return nil, ErrRequire + } + f, err := modfile.ParseLax("go.mod", data, nil) + if err != nil { + base.Errorf("go: %s@%s: parsing go.mod: %v", mod.Path, mod.Version, err) + return nil, ErrRequire + } + + if f.Module == nil { + base.Errorf("go: %s@%s: parsing go.mod: missing module line", mod.Path, mod.Version) + return nil, ErrRequire + } + if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path { + base.Errorf("go: %s@%s: parsing go.mod: unexpected module path %q", mod.Path, mod.Version, mpath) + return nil, ErrRequire + } + if f.Go != nil { + r.versions.LoadOrStore(mod, f.Go.Version) + } + + return r.modFileToList(f), nil +} + +// ErrRequire is the sentinel error returned when Require encounters problems. +// It prints the problems directly to standard error, so that multiple errors +// can be displayed easily. +var ErrRequire = errors.New("error loading module requirements") + +func (*mvsReqs) Max(v1, v2 string) string { + if v1 != "" && semver.Compare(v1, v2) == -1 { + return v2 + } + return v1 +} + +// Upgrade is a no-op, here to implement mvs.Reqs. +// The upgrade logic for go get -u is in ../modget/get.go. +func (*mvsReqs) Upgrade(m module.Version) (module.Version, error) { + return m, nil +} + +func versions(path string) ([]string, error) { + // Note: modfetch.Lookup and repo.Versions are cached, + // so there's no need for us to add extra caching here. + repo, err := modfetch.Lookup(path) + if err != nil { + return nil, err + } + return repo.Versions("") +} + +// Previous returns the tagged version of m.Path immediately prior to +// m.Version, or version "none" if no prior version is tagged. +func (*mvsReqs) Previous(m module.Version) (module.Version, error) { + list, err := versions(m.Path) + if err != nil { + return module.Version{}, err + } + i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 }) + if i > 0 { + return module.Version{Path: m.Path, Version: list[i-1]}, nil + } + return module.Version{Path: m.Path, Version: "none"}, nil +} + +// next returns the next version of m.Path after m.Version. +// It is only used by the exclusion processing in the Required method, +// not called directly by MVS. +func (*mvsReqs) next(m module.Version) (module.Version, error) { + list, err := versions(m.Path) + if err != nil { + return module.Version{}, err + } + i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) > 0 }) + if i < len(list) { + return module.Version{Path: m.Path, Version: list[i]}, nil + } + return module.Version{Path: m.Path, Version: "none"}, nil +} + +func fetch(mod module.Version) (dir string, isLocal bool, err error) { + if mod == Target { + return ModRoot, true, nil + } + if r := Replacement(mod); r.Path != "" { + if r.Version == "" { + dir = r.Path + if !filepath.IsAbs(dir) { + dir = filepath.Join(ModRoot, dir) + } + return dir, true, nil + } + mod = r + } + + dir, err = modfetch.Download(mod) + return dir, false, err +} diff --git a/libgo/go/cmd/go/internal/modload/query.go b/libgo/go/cmd/go/internal/modload/query.go new file mode 100644 index 00000000000..3b550f1db7f --- /dev/null +++ b/libgo/go/cmd/go/internal/modload/query.go @@ -0,0 +1,249 @@ +// 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 modload + +import ( + "cmd/go/internal/modfetch" + "cmd/go/internal/modfetch/codehost" + "cmd/go/internal/module" + "cmd/go/internal/semver" + "fmt" + pathpkg "path" + "strings" +) + +// Query looks up a revision of a given module given a version query string. +// The module must be a complete module path. +// The version must take one of the following forms: +// +// - the literal string "latest", denoting the latest available, allowed tagged version, +// with non-prereleases preferred over prereleases. +// If there are no tagged versions in the repo, latest returns the most recent commit. +// - v1, denoting the latest available tagged version v1.x.x. +// - v1.2, denoting the latest available tagged version v1.2.x. +// - v1.2.3, a semantic version string denoting that tagged version. +// - v1.2.3, >=v1.2.3, +// denoting the version closest to the target and satisfying the given operator, +// with non-prereleases preferred over prereleases. +// - a repository commit identifier, denoting that commit. +// +// If the allowed function is non-nil, Query excludes any versions for which allowed returns false. +// +// If path is the path of the main module and the query is "latest", +// Query returns Target.Version as the version. +func Query(path, query string, allowed func(module.Version) bool) (*modfetch.RevInfo, error) { + if allowed == nil { + allowed = func(module.Version) bool { return true } + } + + // Parse query to detect parse errors (and possibly handle query) + // before any network I/O. + badVersion := func(v string) (*modfetch.RevInfo, error) { + return nil, fmt.Errorf("invalid semantic version %q in range %q", v, query) + } + var ok func(module.Version) bool + var prefix string + var preferOlder bool + switch { + case query == "latest": + ok = allowed + + case strings.HasPrefix(query, "<="): + v := query[len("<="):] + if !semver.IsValid(v) { + return badVersion(v) + } + if isSemverPrefix(v) { + // Refuse to say whether <=v1.2 allows v1.2.3 (remember, @v1.2 might mean v1.2.3). + return nil, fmt.Errorf("ambiguous semantic version %q in range %q", v, query) + } + ok = func(m module.Version) bool { + return semver.Compare(m.Version, v) <= 0 && allowed(m) + } + + case strings.HasPrefix(query, "<"): + v := query[len("<"):] + if !semver.IsValid(v) { + return badVersion(v) + } + ok = func(m module.Version) bool { + return semver.Compare(m.Version, v) < 0 && allowed(m) + } + + case strings.HasPrefix(query, ">="): + v := query[len(">="):] + if !semver.IsValid(v) { + return badVersion(v) + } + ok = func(m module.Version) bool { + return semver.Compare(m.Version, v) >= 0 && allowed(m) + } + preferOlder = true + + case strings.HasPrefix(query, ">"): + v := query[len(">"):] + if !semver.IsValid(v) { + return badVersion(v) + } + if isSemverPrefix(v) { + // Refuse to say whether >v1.2 allows v1.2.3 (remember, @v1.2 might mean v1.2.3). + return nil, fmt.Errorf("ambiguous semantic version %q in range %q", v, query) + } + ok = func(m module.Version) bool { + return semver.Compare(m.Version, v) > 0 && allowed(m) + } + preferOlder = true + + case semver.IsValid(query) && isSemverPrefix(query): + ok = func(m module.Version) bool { + return matchSemverPrefix(query, m.Version) && allowed(m) + } + prefix = query + "." + + case semver.IsValid(query): + vers := module.CanonicalVersion(query) + if !allowed(module.Version{Path: path, Version: vers}) { + return nil, fmt.Errorf("%s@%s excluded", path, vers) + } + return modfetch.Stat(path, vers) + + default: + // Direct lookup of semantic version or commit identifier. + info, err := modfetch.Stat(path, query) + if err != nil { + return nil, err + } + if !allowed(module.Version{Path: path, Version: info.Version}) { + return nil, fmt.Errorf("%s@%s excluded", path, info.Version) + } + return info, nil + } + + if path == Target.Path { + if query != "latest" { + return nil, fmt.Errorf("can't query specific version (%q) for the main module (%s)", query, path) + } + if !allowed(Target) { + return nil, fmt.Errorf("internal error: main module version is not allowed") + } + return &modfetch.RevInfo{Version: Target.Version}, nil + } + + // Load versions and execute query. + repo, err := modfetch.Lookup(path) + if err != nil { + return nil, err + } + versions, err := repo.Versions(prefix) + if err != nil { + return nil, err + } + + if preferOlder { + for _, v := range versions { + if semver.Prerelease(v) == "" && ok(module.Version{Path: path, Version: v}) { + return repo.Stat(v) + } + } + for _, v := range versions { + if semver.Prerelease(v) != "" && ok(module.Version{Path: path, Version: v}) { + return repo.Stat(v) + } + } + } else { + for i := len(versions) - 1; i >= 0; i-- { + v := versions[i] + if semver.Prerelease(v) == "" && ok(module.Version{Path: path, Version: v}) { + return repo.Stat(v) + } + } + for i := len(versions) - 1; i >= 0; i-- { + v := versions[i] + if semver.Prerelease(v) != "" && ok(module.Version{Path: path, Version: v}) { + return repo.Stat(v) + } + } + } + + if query == "latest" { + // Special case for "latest": if no tags match, use latest commit in repo, + // provided it is not excluded. + if info, err := repo.Latest(); err == nil && allowed(module.Version{Path: path, Version: info.Version}) { + return info, nil + } + } + + return nil, fmt.Errorf("no matching versions for query %q", query) +} + +// isSemverPrefix reports whether v is a semantic version prefix: v1 or v1.2 (not v1.2.3). +// The caller is assumed to have checked that semver.IsValid(v) is true. +func isSemverPrefix(v string) bool { + dots := 0 + for i := 0; i < len(v); i++ { + switch v[i] { + case '-', '+': + return false + case '.': + dots++ + if dots >= 2 { + return false + } + } + } + return true +} + +// matchSemverPrefix reports whether the shortened semantic version p +// matches the full-width (non-shortened) semantic version v. +func matchSemverPrefix(p, v string) bool { + return len(v) > len(p) && v[len(p)] == '.' && v[:len(p)] == p +} + +// QueryPackage looks up a revision of a module containing path. +// +// If multiple modules with revisions matching the query provide the requested +// package, QueryPackage picks the one with the longest module path. +// +// If the path is in the the main module and the query is "latest", +// QueryPackage returns Target as the version. +func QueryPackage(path, query string, allowed func(module.Version) bool) (module.Version, *modfetch.RevInfo, error) { + if _, ok := dirInModule(path, Target.Path, ModRoot, true); ok { + if query != "latest" { + return module.Version{}, nil, fmt.Errorf("can't query specific version (%q) for package %s in the main module (%s)", query, path, Target.Path) + } + if !allowed(Target) { + return module.Version{}, nil, fmt.Errorf("internal error: package %s is in the main module (%s), but version is not allowed", path, Target.Path) + } + return Target, &modfetch.RevInfo{Version: Target.Version}, nil + } + + finalErr := errMissing + for p := path; p != "."; p = pathpkg.Dir(p) { + info, err := Query(p, query, allowed) + if err != nil { + if _, ok := err.(*codehost.VCSError); ok { + // A VCSError means we know where to find the code, + // we just can't. Abort search. + return module.Version{}, nil, err + } + if finalErr == errMissing { + finalErr = err + } + continue + } + m := module.Version{Path: p, Version: info.Version} + root, isLocal, err := fetch(m) + if err != nil { + return module.Version{}, nil, err + } + _, ok := dirInModule(path, m.Path, root, isLocal) + if ok { + return m, info, nil + } + } + + return module.Version{}, nil, finalErr +} diff --git a/libgo/go/cmd/go/internal/modload/query_test.go b/libgo/go/cmd/go/internal/modload/query_test.go new file mode 100644 index 00000000000..7f3ffabef74 --- /dev/null +++ b/libgo/go/cmd/go/internal/modload/query_test.go @@ -0,0 +1,151 @@ +// 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 modload + +import ( + "internal/testenv" + "io/ioutil" + "log" + "os" + "path" + "path/filepath" + "strings" + "testing" + + "cmd/go/internal/modfetch" + "cmd/go/internal/modfetch/codehost" + "cmd/go/internal/module" +) + +func TestMain(m *testing.M) { + os.Exit(testMain(m)) +} + +func testMain(m *testing.M) int { + dir, err := ioutil.TempDir("", "modload-test-") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(dir) + modfetch.PkgMod = filepath.Join(dir, "pkg/mod") + codehost.WorkRoot = filepath.Join(dir, "codework") + return m.Run() +} + +var ( + queryRepo = "vcs-test.golang.org/git/querytest.git" + queryRepoV2 = queryRepo + "/v2" + queryRepoV3 = queryRepo + "/v3" + + // Empty version list (no semver tags), not actually empty. + emptyRepo = "vcs-test.golang.org/git/emptytest.git" +) + +var queryTests = []struct { + path string + query string + allow string + vers string + err string +}{ + /* + git init + echo module vcs-test.golang.org/git/querytest.git >go.mod + git add go.mod + git commit -m v1 go.mod + git tag start + for i in v0.0.0-pre1 v0.0.0 v0.0.1 v0.0.2 v0.0.3 v0.1.0 v0.1.1 v0.1.2 v0.3.0 v1.0.0 v1.1.0 v1.9.0 v1.9.9 v1.9.10-pre1; do + echo before $i >status + git add status + git commit -m "before $i" status + echo at $i >status + git commit -m "at $i" status + git tag $i + done + git tag favorite v0.0.3 + + git branch v2 start + git checkout v2 + echo module vcs-test.golang.org/git/querytest.git/v2 >go.mod + git commit -m v2 go.mod + for i in v2.0.0 v2.1.0 v2.2.0 v2.5.5; do + echo before $i >status + git add status + git commit -m "before $i" status + echo at $i >status + git commit -m "at $i" status + git tag $i + done + echo after v2.5.5 >status + git commit -m 'after v2.5.5' status + git checkout master + zip -r ../querytest.zip + gsutil cp ../querytest.zip gs://vcs-test/git/querytest.zip + curl 'https://vcs-test.golang.org/git/querytest?go-get=1' + */ + {path: queryRepo, query: "v0.0.0", vers: "v0.0.1"}, + {path: queryRepo, query: ">=v0.0.0", vers: "v0.0.0"}, + {path: queryRepo, query: "v0.0.1", vers: "v0.0.1"}, + {path: queryRepo, query: "v0.0.1+foo", vers: "v0.0.1"}, + {path: queryRepo, query: "v0.0.99", err: `unknown revision v0.0.99`}, + {path: queryRepo, query: "v0", vers: "v0.3.0"}, + {path: queryRepo, query: "v0.1", vers: "v0.1.2"}, + {path: queryRepo, query: "v0.2", err: `no matching versions for query "v0.2"`}, + {path: queryRepo, query: "v0.0", vers: "v0.0.3"}, + {path: queryRepo, query: "latest", vers: "v1.9.9"}, + {path: queryRepo, query: "latest", allow: "NOMATCH", err: `no matching versions for query "latest"`}, + {path: queryRepo, query: ">v1.9.9", vers: "v1.9.10-pre1"}, + {path: queryRepo, query: ">v1.10.0", err: `no matching versions for query ">v1.10.0"`}, + {path: queryRepo, query: ">=v1.10.0", err: `no matching versions for query ">=v1.10.0"`}, + {path: queryRepo, query: "6cf84eb", vers: "v0.0.2-0.20180704023347-6cf84ebaea54"}, + {path: queryRepo, query: "start", vers: "v0.0.0-20180704023101-5e9e31667ddf"}, + {path: queryRepo, query: "7a1b6bf", vers: "v0.1.0"}, + + {path: queryRepoV2, query: "v0.0.0", vers: "v2.0.0"}, + {path: queryRepoV2, query: ">=v0.0.0", vers: "v2.0.0"}, + {path: queryRepoV2, query: "v0.0.1+foo", vers: "v2.0.0-20180704023347-179bc86b1be3"}, + {path: queryRepoV2, query: "latest", vers: "v2.5.5"}, + + {path: queryRepoV3, query: "latest", vers: "v3.0.0-20180704024501-e0cf3de987e6"}, + + {path: emptyRepo, query: "latest", vers: "v0.0.0-20180704023549-7bb914627242"}, + {path: emptyRepo, query: ">v0.0.0", err: `no matching versions for query ">v0.0.0"`}, + {path: emptyRepo, query: " ? @ [ \ ] ^ _ ` { | } ~ + // We disallow some shell special characters: " ' * < > ? ` | + // (Note that some of those are disallowed by the Windows file system as well.) + // We also disallow path separators / : and \ (fileNameOK is only called on path element characters). + // We allow spaces (U+0020) in file names. + const allowed = "!#$%&()+,-.=@[]^_{}~ " + if '0' <= r && r <= '9' || 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' { + return true + } + for i := 0; i < len(allowed); i++ { + if rune(allowed[i]) == r { + return true + } + } + return false + } + // It may be OK to add more ASCII punctuation here, but only carefully. + // For example Windows disallows < > \, and macOS disallows :, so we must not allow those. + return unicode.IsLetter(r) +} + +// CheckPath checks that a module path is valid. +func CheckPath(path string) error { + if err := checkPath(path, false); err != nil { + return fmt.Errorf("malformed module path %q: %v", path, err) + } + i := strings.Index(path, "/") + if i < 0 { + i = len(path) + } + if i == 0 { + return fmt.Errorf("malformed module path %q: leading slash", path) + } + if !strings.Contains(path[:i], ".") { + return fmt.Errorf("malformed module path %q: missing dot in first path element", path) + } + if path[0] == '-' { + return fmt.Errorf("malformed module path %q: leading dash in first path element", path) + } + for _, r := range path[:i] { + if !firstPathOK(r) { + return fmt.Errorf("malformed module path %q: invalid char %q in first path element", path, r) + } + } + if _, _, ok := SplitPathVersion(path); !ok { + return fmt.Errorf("malformed module path %q: invalid version", path) + } + return nil +} + +// CheckImportPath checks that an import path is valid. +func CheckImportPath(path string) error { + if err := checkPath(path, false); err != nil { + return fmt.Errorf("malformed import path %q: %v", path, err) + } + return nil +} + +// 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). +func checkPath(path string, fileName bool) error { + if !utf8.ValidString(path) { + return fmt.Errorf("invalid UTF-8") + } + if path == "" { + return fmt.Errorf("empty string") + } + if strings.Contains(path, "..") { + return fmt.Errorf("double dot") + } + if strings.Contains(path, "//") { + return fmt.Errorf("double slash") + } + if path[len(path)-1] == '/' { + return fmt.Errorf("trailing slash") + } + elemStart := 0 + for i, r := range path { + if r == '/' { + if err := checkElem(path[elemStart:i], fileName); err != nil { + return err + } + elemStart = i + 1 + } + } + if err := checkElem(path[elemStart:], fileName); err != nil { + return err + } + return nil +} + +// checkElem checks whether an individual path element is valid. +// fileName indicates whether the element is a file name (not a directory name). +func checkElem(elem string, fileName bool) error { + if elem == "" { + return fmt.Errorf("empty path element") + } + if strings.Count(elem, ".") == len(elem) { + return fmt.Errorf("invalid path element %q", elem) + } + if elem[0] == '.' && !fileName { + return fmt.Errorf("leading dot in path element") + } + if elem[len(elem)-1] == '.' { + return fmt.Errorf("trailing dot in path element") + } + charOK := pathOK + if fileName { + charOK = fileNameOK + } + for _, r := range elem { + if !charOK(r) { + return fmt.Errorf("invalid char %q", r) + } + } + + // Windows disallows a bunch of path elements, sadly. + // See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file + short := elem + if i := strings.Index(short, "."); i >= 0 { + short = short[:i] + } + for _, bad := range badWindowsNames { + if strings.EqualFold(bad, short) { + return fmt.Errorf("disallowed path element %q", elem) + } + } + return nil +} + +// CheckFilePath checks whether a slash-separated file path is valid. +func CheckFilePath(path string) error { + if err := checkPath(path, true); err != nil { + return fmt.Errorf("malformed file path %q: %v", path, err) + } + return nil +} + +// badWindowsNames are the reserved file path elements on Windows. +// See https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file +var badWindowsNames = []string{ + "CON", + "PRN", + "AUX", + "NUL", + "COM1", + "COM2", + "COM3", + "COM4", + "COM5", + "COM6", + "COM7", + "COM8", + "COM9", + "LPT1", + "LPT2", + "LPT3", + "LPT4", + "LPT5", + "LPT6", + "LPT7", + "LPT8", + "LPT9", +} + +// SplitPathVersion returns prefix and major version such that prefix+pathMajor == path +// and version is either empty or "/vN" for N >= 2. +// As a special case, gopkg.in paths are recognized directly; +// they require ".vN" instead of "/vN", and for all N, not just N >= 2. +func SplitPathVersion(path string) (prefix, pathMajor string, ok bool) { + if strings.HasPrefix(path, "gopkg.in/") { + return splitGopkgIn(path) + } + + i := len(path) + dot := false + for i > 0 && ('0' <= path[i-1] && path[i-1] <= '9' || path[i-1] == '.') { + if path[i-1] == '.' { + dot = true + } + i-- + } + if i <= 1 || path[i-1] != 'v' || path[i-2] != '/' { + return path, "", true + } + prefix, pathMajor = path[:i-2], path[i-2:] + if dot || len(pathMajor) <= 2 || pathMajor[2] == '0' || pathMajor == "/v1" { + return path, "", false + } + return prefix, pathMajor, true +} + +// splitGopkgIn is like SplitPathVersion but only for gopkg.in paths. +func splitGopkgIn(path string) (prefix, pathMajor string, ok bool) { + if !strings.HasPrefix(path, "gopkg.in/") { + return path, "", false + } + i := len(path) + if strings.HasSuffix(path, "-unstable") { + i -= len("-unstable") + } + for i > 0 && ('0' <= path[i-1] && path[i-1] <= '9') { + i-- + } + if i <= 1 || path[i-1] != 'v' || path[i-2] != '.' { + // All gopkg.in paths must end in vN for some N. + return path, "", false + } + prefix, pathMajor = path[:i-2], path[i-2:] + if len(pathMajor) <= 2 || pathMajor[2] == '0' && pathMajor != ".v0" { + return path, "", false + } + return prefix, pathMajor, true +} + +// MatchPathMajor reports whether the semantic version v +// matches the path major version pathMajor. +func MatchPathMajor(v, pathMajor string) bool { + if strings.HasPrefix(pathMajor, ".v") && strings.HasSuffix(pathMajor, "-unstable") { + pathMajor = strings.TrimSuffix(pathMajor, "-unstable") + } + if strings.HasPrefix(v, "v0.0.0-") && pathMajor == ".v1" { + // Allow old bug in pseudo-versions that generated v0.0.0- pseudoversion for gopkg .v1. + // For example, gopkg.in/yaml.v2@v2.2.1's go.mod requires gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405. + return true + } + m := semver.Major(v) + if pathMajor == "" { + return m == "v0" || m == "v1" || semver.Build(v) == "+incompatible" + } + return (pathMajor[0] == '/' || pathMajor[0] == '.') && m == pathMajor[1:] +} + +// CanonicalVersion returns the canonical form of the version string v. +// It is the same as semver.Canonical(v) except that it preserves the special build suffix "+incompatible". +func CanonicalVersion(v string) string { + cv := semver.Canonical(v) + if semver.Build(v) == "+incompatible" { + cv += "+incompatible" + } + return cv +} + +// Sort sorts the list by Path, breaking ties by comparing Versions. +func Sort(list []Version) { + sort.Slice(list, func(i, j int) bool { + mi := list[i] + mj := list[j] + if mi.Path != mj.Path { + return mi.Path < mj.Path + } + // To help go.sum formatting, allow version/file. + // Compare semver prefix by semver rules, + // file by string order. + vi := mi.Version + vj := mj.Version + var fi, fj string + if k := strings.Index(vi, "/"); k >= 0 { + vi, fi = vi[:k], vi[k:] + } + if k := strings.Index(vj, "/"); k >= 0 { + vj, fj = vj[:k], vj[k:] + } + if vi != vj { + return semver.Compare(vi, vj) < 0 + } + return fi < fj + }) +} + +// Safe encodings +// +// Module paths appear as substrings of file system paths +// (in the download cache) and of web server URLs in the proxy protocol. +// In general we cannot rely on file systems to be case-sensitive, +// nor can we rely on web servers, since they read from file systems. +// That is, we cannot rely on the file system to keep rsc.io/QUOTE +// and rsc.io/quote separate. Windows and macOS don't. +// Instead, we must never require two different casings of a file path. +// Because we want the download cache to match the proxy protocol, +// and because we want the proxy protocol to be possible to serve +// from a tree of static files (which might be stored on a case-insensitive +// file system), the proxy protocol must never require two different casings +// of a URL path either. +// +// One possibility would be to make the safe encoding be the lowercase +// hexadecimal encoding of the actual path bytes. This would avoid ever +// needing different casings of a file path, but it would be fairly illegible +// to most programmers when those paths appeared in the file system +// (including in file paths in compiler errors and stack traces) +// in web server logs, and so on. Instead, we want a safe encoding that +// leaves most paths unaltered. +// +// The safe encoding is this: +// replace every uppercase letter with an exclamation mark +// followed by the letter's lowercase equivalent. +// +// For example, +// github.com/Azure/azure-sdk-for-go -> github.com/!azure/azure-sdk-for-go. +// github.com/GoogleCloudPlatform/cloudsql-proxy -> github.com/!google!cloud!platform/cloudsql-proxy +// github.com/Sirupsen/logrus -> github.com/!sirupsen/logrus. +// +// Import paths that avoid upper-case letters are left unchanged. +// Note that because import paths are ASCII-only and avoid various +// problematic punctuation (like : < and >), the safe encoding is also ASCII-only +// and avoids the same problematic punctuation. +// +// Import paths have never allowed exclamation marks, so there is no +// need to define how to encode a literal !. +// +// Although paths are disallowed from using Unicode (see pathOK above), +// the eventual plan is to allow Unicode letters as well, to assume that +// file systems and URLs are Unicode-safe (storing UTF-8), and apply +// the !-for-uppercase convention. Note however that not all runes that +// are different but case-fold equivalent are an upper/lower pair. +// For example, U+004B ('K'), U+006B ('k'), and U+212A ('K' for Kelvin) +// are considered to case-fold to each other. When we do add Unicode +// letters, we must not assume that upper/lower are the only case-equivalent pairs. +// Perhaps the Kelvin symbol would be disallowed entirely, for example. +// Or perhaps it would encode as "!!k", or perhaps as "(212A)". +// +// Also, it would be nice to allow Unicode marks as well as letters, +// but marks include combining marks, and then we must deal not +// only with case folding but also normalization: both U+00E9 ('é') +// and U+0065 U+0301 ('e' followed by combining acute accent) +// look the same on the page and are treated by some file systems +// as the same path. If we do allow Unicode marks in paths, there +// must be some kind of normalization to allow only one canonical +// encoding of any character used in an import path. + +// EncodePath returns the safe encoding of the given module path. +// It fails if the module path is invalid. +func EncodePath(path string) (encoding string, err error) { + if err := CheckPath(path); err != nil { + return "", err + } + + return encodeString(path) +} + +// EncodeVersion returns the safe encoding of the given module version. +// Versions are allowed to be in non-semver form but must be valid file names +// and not contain exclamation marks. +func EncodeVersion(v string) (encoding string, err error) { + if err := checkElem(v, true); err != nil || strings.Contains(v, "!") { + return "", fmt.Errorf("disallowed version string %q", v) + } + return encodeString(v) +} + +func encodeString(s string) (encoding string, err error) { + haveUpper := false + for _, r := range s { + if r == '!' || r >= utf8.RuneSelf { + // This should be disallowed by CheckPath, but diagnose anyway. + // The correctness of the encoding loop below depends on it. + return "", fmt.Errorf("internal error: inconsistency in EncodePath") + } + if 'A' <= r && r <= 'Z' { + haveUpper = true + } + } + + if !haveUpper { + return s, nil + } + + var buf []byte + for _, r := range s { + if 'A' <= r && r <= 'Z' { + buf = append(buf, '!', byte(r+'a'-'A')) + } else { + buf = append(buf, byte(r)) + } + } + return string(buf), nil +} + +// DecodePath returns the module path of the given safe encoding. +// It fails if the encoding is invalid or encodes an invalid path. +func DecodePath(encoding string) (path string, err error) { + path, ok := decodeString(encoding) + if !ok { + return "", fmt.Errorf("invalid module path encoding %q", encoding) + } + if err := CheckPath(path); err != nil { + return "", fmt.Errorf("invalid module path encoding %q: %v", encoding, err) + } + return path, nil +} + +// DecodeVersion returns the version string for the given safe encoding. +// It fails if the encoding is invalid or encodes an invalid version. +// Versions are allowed to be in non-semver form but must be valid file names +// and not contain exclamation marks. +func DecodeVersion(encoding string) (v string, err error) { + v, ok := decodeString(encoding) + if !ok { + return "", fmt.Errorf("invalid version encoding %q", encoding) + } + if err := checkElem(v, true); err != nil { + return "", fmt.Errorf("disallowed version string %q", v) + } + return v, nil +} + +func decodeString(encoding string) (string, bool) { + var buf []byte + + bang := false + for _, r := range encoding { + if r >= utf8.RuneSelf { + return "", false + } + if bang { + bang = false + if r < 'a' || 'z' < r { + return "", false + } + buf = append(buf, byte(r+'A'-'a')) + continue + } + if r == '!' { + bang = true + continue + } + if 'A' <= r && r <= 'Z' { + return "", false + } + buf = append(buf, byte(r)) + } + if bang { + return "", false + } + return string(buf), true +} diff --git a/libgo/go/cmd/go/internal/module/module_test.go b/libgo/go/cmd/go/internal/module/module_test.go new file mode 100644 index 00000000000..f21d620d328 --- /dev/null +++ b/libgo/go/cmd/go/internal/module/module_test.go @@ -0,0 +1,318 @@ +// 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 module + +import "testing" + +var checkTests = []struct { + path string + version string + ok bool +}{ + {"rsc.io/quote", "0.1.0", false}, + {"rsc io/quote", "v1.0.0", false}, + + {"github.com/go-yaml/yaml", "v0.8.0", true}, + {"github.com/go-yaml/yaml", "v1.0.0", true}, + {"github.com/go-yaml/yaml", "v2.0.0", false}, + {"github.com/go-yaml/yaml", "v2.1.5", false}, + {"github.com/go-yaml/yaml", "v3.0.0", false}, + + {"github.com/go-yaml/yaml/v2", "v1.0.0", false}, + {"github.com/go-yaml/yaml/v2", "v2.0.0", true}, + {"github.com/go-yaml/yaml/v2", "v2.1.5", true}, + {"github.com/go-yaml/yaml/v2", "v3.0.0", false}, + + {"gopkg.in/yaml.v0", "v0.8.0", true}, + {"gopkg.in/yaml.v0", "v1.0.0", false}, + {"gopkg.in/yaml.v0", "v2.0.0", false}, + {"gopkg.in/yaml.v0", "v2.1.5", false}, + {"gopkg.in/yaml.v0", "v3.0.0", false}, + + {"gopkg.in/yaml.v1", "v0.8.0", false}, + {"gopkg.in/yaml.v1", "v1.0.0", true}, + {"gopkg.in/yaml.v1", "v2.0.0", false}, + {"gopkg.in/yaml.v1", "v2.1.5", false}, + {"gopkg.in/yaml.v1", "v3.0.0", false}, + + // For gopkg.in, .v1 means v1 only (not v0). + // But early versions of vgo still generated v0 pseudo-versions for it. + // Even though now we'd generate those as v1 pseudo-versions, + // we accept the old pseudo-versions to avoid breaking existing go.mod files. + // For example gopkg.in/yaml.v2@v2.2.1's go.mod requires check.v1 at a v0 pseudo-version. + {"gopkg.in/check.v1", "v0.0.0", false}, + {"gopkg.in/check.v1", "v0.0.0-20160102150405-abcdef123456", true}, + + {"gopkg.in/yaml.v2", "v1.0.0", false}, + {"gopkg.in/yaml.v2", "v2.0.0", true}, + {"gopkg.in/yaml.v2", "v2.1.5", true}, + {"gopkg.in/yaml.v2", "v3.0.0", false}, + + {"rsc.io/quote", "v17.0.0", false}, + {"rsc.io/quote", "v17.0.0+incompatible", true}, +} + +func TestCheck(t *testing.T) { + for _, tt := range checkTests { + err := Check(tt.path, tt.version) + if tt.ok && err != nil { + t.Errorf("Check(%q, %q) = %v, wanted nil error", tt.path, tt.version, err) + } else if !tt.ok && err == nil { + t.Errorf("Check(%q, %q) succeeded, wanted error", tt.path, tt.version) + } + } +} + +var checkPathTests = []struct { + path string + ok bool + importOK bool + fileOK bool +}{ + {"x.y/z", true, true, true}, + {"x.y", true, true, true}, + + {"", false, false, false}, + {"x.y/\xFFz", false, false, false}, + {"/x.y/z", false, false, false}, + {"x./z", false, false, false}, + {".x/z", false, false, true}, + {"-x/z", false, true, true}, + {"x..y/z", false, false, false}, + {"x.y/z/../../w", false, false, false}, + {"x.y//z", false, false, false}, + {"x.y/z//w", false, false, false}, + {"x.y/z/", false, false, false}, + + {"x.y/z/v0", false, true, true}, + {"x.y/z/v1", false, true, true}, + {"x.y/z/v2", true, true, true}, + {"x.y/z/v2.0", false, true, true}, + {"X.y/z", false, true, true}, + + {"!x.y/z", false, false, true}, + {"_x.y/z", false, true, true}, + {"x.y!/z", false, false, true}, + {"x.y\"/z", false, false, false}, + {"x.y#/z", false, false, true}, + {"x.y$/z", false, false, true}, + {"x.y%/z", false, false, true}, + {"x.y&/z", false, false, true}, + {"x.y'/z", false, false, false}, + {"x.y(/z", false, false, true}, + {"x.y)/z", false, false, true}, + {"x.y*/z", false, false, false}, + {"x.y+/z", false, true, true}, + {"x.y,/z", false, false, true}, + {"x.y-/z", true, true, true}, + {"x.y./zt", false, false, false}, + {"x.y:/z", false, false, false}, + {"x.y;/z", false, false, false}, + {"x.y/z", false, false, false}, + {"x.y?/z", false, false, false}, + {"x.y@/z", false, false, true}, + {"x.y[/z", false, false, true}, + {"x.y\\/z", false, false, false}, + {"x.y]/z", false, false, true}, + {"x.y^/z", false, false, true}, + {"x.y_/z", false, true, true}, + {"x.y`/z", false, false, false}, + {"x.y{/z", false, false, true}, + {"x.y}/z", false, false, true}, + {"x.y~/z", false, true, true}, + {"x.y/z!", false, false, true}, + {"x.y/z\"", false, false, false}, + {"x.y/z#", false, false, true}, + {"x.y/z$", false, false, true}, + {"x.y/z%", false, false, true}, + {"x.y/z&", false, false, true}, + {"x.y/z'", false, false, false}, + {"x.y/z(", false, false, true}, + {"x.y/z)", false, false, true}, + {"x.y/z*", false, false, false}, + {"x.y/z+", true, true, true}, + {"x.y/z,", false, false, true}, + {"x.y/z-", true, true, true}, + {"x.y/z.t", true, true, true}, + {"x.y/z/t", true, true, true}, + {"x.y/z:", false, false, false}, + {"x.y/z;", false, false, false}, + {"x.y/z<", false, false, false}, + {"x.y/z=", false, false, true}, + {"x.y/z>", false, false, false}, + {"x.y/z?", false, false, false}, + {"x.y/z@", false, false, true}, + {"x.y/z[", false, false, true}, + {"x.y/z\\", false, false, false}, + {"x.y/z]", false, false, true}, + {"x.y/z^", false, false, true}, + {"x.y/z_", true, true, true}, + {"x.y/z`", false, false, false}, + {"x.y/z{", false, false, true}, + {"x.y/z}", false, false, true}, + {"x.y/z~", true, true, true}, + {"x.y/x.foo", true, true, true}, + {"x.y/aux.foo", false, false, false}, + {"x.y/prn", false, false, false}, + {"x.y/prn2", true, true, true}, + {"x.y/com", true, true, true}, + {"x.y/com1", false, false, false}, + {"x.y/com1.txt", false, false, false}, + {"x.y/calm1", true, true, true}, + {"github.com/!123/logrus", false, false, true}, + + // TODO: CL 41822 allowed Unicode letters in old "go get" + // without due consideration of the implications, and only on github.com (!). + // For now, we disallow non-ASCII characters in module mode, + // in both module paths and general import paths, + // until we can get the implications right. + // When we do, we'll enable them everywhere, not just for GitHub. + {"github.com/user/unicode/испытание", false, false, true}, + + {"../x", false, false, false}, + {"./y", false, false, false}, + {"x:y", false, false, false}, + {`\temp\foo`, false, false, false}, + {".gitignore", false, false, true}, + {".github/ISSUE_TEMPLATE", false, false, true}, + {"x☺y", false, false, false}, +} + +func TestCheckPath(t *testing.T) { + for _, tt := range checkPathTests { + err := CheckPath(tt.path) + if tt.ok && err != nil { + t.Errorf("CheckPath(%q) = %v, wanted nil error", tt.path, err) + } else if !tt.ok && err == nil { + t.Errorf("CheckPath(%q) succeeded, wanted error", tt.path) + } + + err = CheckImportPath(tt.path) + if tt.importOK && err != nil { + t.Errorf("CheckImportPath(%q) = %v, wanted nil error", tt.path, err) + } else if !tt.importOK && err == nil { + t.Errorf("CheckImportPath(%q) succeeded, wanted error", tt.path) + } + + err = CheckFilePath(tt.path) + if tt.fileOK && err != nil { + t.Errorf("CheckFilePath(%q) = %v, wanted nil error", tt.path, err) + } else if !tt.fileOK && err == nil { + t.Errorf("CheckFilePath(%q) succeeded, wanted error", tt.path) + } + } +} + +var splitPathVersionTests = []struct { + pathPrefix string + version string +}{ + {"x.y/z", ""}, + {"x.y/z", "/v2"}, + {"x.y/z", "/v3"}, + {"gopkg.in/yaml", ".v0"}, + {"gopkg.in/yaml", ".v1"}, + {"gopkg.in/yaml", ".v2"}, + {"gopkg.in/yaml", ".v3"}, +} + +func TestSplitPathVersion(t *testing.T) { + for _, tt := range splitPathVersionTests { + pathPrefix, version, ok := SplitPathVersion(tt.pathPrefix + tt.version) + if pathPrefix != tt.pathPrefix || version != tt.version || !ok { + t.Errorf("SplitPathVersion(%q) = %q, %q, %v, want %q, %q, true", tt.pathPrefix+tt.version, pathPrefix, version, ok, tt.pathPrefix, tt.version) + } + } + + for _, tt := range checkPathTests { + pathPrefix, version, ok := SplitPathVersion(tt.path) + if pathPrefix+version != tt.path { + t.Errorf("SplitPathVersion(%q) = %q, %q, %v, doesn't add to input", tt.path, pathPrefix, version, ok) + } + } +} + +var encodeTests = []struct { + path string + enc string // empty means same as path +}{ + {path: "ascii.com/abcdefghijklmnopqrstuvwxyz.-+/~_0123456789"}, + {path: "github.com/GoogleCloudPlatform/omega", enc: "github.com/!google!cloud!platform/omega"}, +} + +func TestEncodePath(t *testing.T) { + // Check invalid paths. + for _, tt := range checkPathTests { + if !tt.ok { + _, err := EncodePath(tt.path) + if err == nil { + t.Errorf("EncodePath(%q): succeeded, want error (invalid path)", tt.path) + } + } + } + + // Check encodings. + for _, tt := range encodeTests { + enc, err := EncodePath(tt.path) + if err != nil { + t.Errorf("EncodePath(%q): unexpected error: %v", tt.path, err) + continue + } + want := tt.enc + if want == "" { + want = tt.path + } + if enc != want { + t.Errorf("EncodePath(%q) = %q, want %q", tt.path, enc, want) + } + } +} + +var badDecode = []string{ + "github.com/GoogleCloudPlatform/omega", + "github.com/!google!cloud!platform!/omega", + "github.com/!0google!cloud!platform/omega", + "github.com/!_google!cloud!platform/omega", + "github.com/!!google!cloud!platform/omega", + "", +} + +func TestDecodePath(t *testing.T) { + // Check invalid decodings. + for _, bad := range badDecode { + _, err := DecodePath(bad) + if err == nil { + t.Errorf("DecodePath(%q): succeeded, want error (invalid decoding)", bad) + } + } + + // Check invalid paths (or maybe decodings). + for _, tt := range checkPathTests { + if !tt.ok { + path, err := DecodePath(tt.path) + if err == nil { + t.Errorf("DecodePath(%q) = %q, want error (invalid path)", tt.path, path) + } + } + } + + // Check encodings. + for _, tt := range encodeTests { + enc := tt.enc + if enc == "" { + enc = tt.path + } + path, err := DecodePath(enc) + if err != nil { + t.Errorf("DecodePath(%q): unexpected error: %v", enc, err) + continue + } + if path != tt.path { + t.Errorf("DecodePath(%q) = %q, want %q", enc, path, tt.path) + } + } +} diff --git a/libgo/go/cmd/go/internal/mvs/mvs.go b/libgo/go/cmd/go/internal/mvs/mvs.go new file mode 100644 index 00000000000..8ec9162dabc --- /dev/null +++ b/libgo/go/cmd/go/internal/mvs/mvs.go @@ -0,0 +1,368 @@ +// 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 mvs implements Minimal Version Selection. +// See https://research.swtch.com/vgo-mvs. +package mvs + +import ( + "fmt" + "sort" + "sync" + + "cmd/go/internal/base" + "cmd/go/internal/module" + "cmd/go/internal/par" +) + +// A Reqs is the requirement graph on which Minimal Version Selection (MVS) operates. +// +// The version strings are opaque except for the special version "none" +// (see the documentation for module.Version). In particular, MVS does not +// assume that the version strings are semantic versions; instead, the Max method +// gives access to the comparison operation. +// +// It must be safe to call methods on a Reqs from multiple goroutines simultaneously. +// Because a Reqs may read the underlying graph from the network on demand, +// the MVS algorithms parallelize the traversal to overlap network delays. +type Reqs interface { + // Required returns the module versions explicitly required by m itself. + // The caller must not modify the returned list. + Required(m module.Version) ([]module.Version, error) + + // Max returns the maximum of v1 and v2 (it returns either v1 or v2). + // + // For all versions v, Max(v, "none") must be v, + // and for the tanget passed as the first argument to MVS functions, + // Max(target, v) must be target. + // + // 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 + + // Upgrade returns the upgraded version of m, + // for use during an UpgradeAll operation. + // If m should be kept as is, Upgrade returns m. + // If m is not yet used in the build, then m.Version will be "none". + // More typically, m.Version will be the version required + // by some other module in the build. + // + // If no module version is available for the given path, + // Upgrade returns a non-nil error. + // 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) + + // Previous returns the version of m.Path immediately prior to m.Version, + // or "none" if no such version is known. + Previous(m module.Version) (module.Version, error) +} + +type MissingModuleError struct { + Module module.Version +} + +func (e *MissingModuleError) Error() string { + return fmt.Sprintf("missing module: %v", e.Module) +} + +// BuildList returns the build list for the target module. +func BuildList(target module.Version, reqs Reqs) ([]module.Version, error) { + return buildList(target, reqs, nil) +} + +func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) module.Version) ([]module.Version, error) { + // Explore work graph in parallel in case reqs.Required + // does high-latency network operations. + var work par.Work + work.Add(target) + var ( + mu sync.Mutex + min = map[string]string{target.Path: target.Version} + firstErr error + ) + work.Do(10, func(item interface{}) { + m := item.(module.Version) + required, err := reqs.Required(m) + + mu.Lock() + if err != nil && firstErr == nil { + firstErr = err + } + if firstErr != nil { + mu.Unlock() + return + } + if v, ok := min[m.Path]; !ok || reqs.Max(v, m.Version) != v { + min[m.Path] = m.Version + } + mu.Unlock() + + for _, r := range required { + if r.Path == "" { + base.Errorf("Required(%v) returned zero module in list", m) + continue + } + work.Add(r) + } + + if upgrade != nil { + u := upgrade(m) + if u.Path == "" { + base.Errorf("Upgrade(%v) returned zero module", m) + return + } + work.Add(u) + } + }) + + if firstErr != nil { + return nil, firstErr + } + if v := min[target.Path]; v != target.Version { + panic(fmt.Sprintf("mistake: chose version %q instead of target %+v", v, target)) // TODO: Don't panic. + } + + list := []module.Version{target} + listed := map[string]bool{target.Path: true} + for i := 0; i < len(list); i++ { + m := list[i] + required, err := reqs.Required(m) + if err != nil { + return nil, err + } + for _, r := range required { + 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. + } + if !listed[r.Path] { + list = append(list, module.Version{Path: r.Path, Version: v}) + listed[r.Path] = true + } + } + } + + tail := list[1:] + sort.Slice(tail, func(i, j int) bool { + return tail[i].Path < tail[j].Path + }) + return list, nil +} + +// Req returns the minimal requirement list for the target module +// that results in the given build list, with the constraint that all +// module paths listed in base must appear in the returned list. +func Req(target module.Version, list []module.Version, base []string, reqs Reqs) ([]module.Version, error) { + // Note: Not running in parallel because we assume + // that list came from a previous operation that paged + // in all the requirements, so there's no I/O to overlap now. + + // Compute postorder, cache requirements. + var postorder []module.Version + reqCache := map[module.Version][]module.Version{} + reqCache[target] = nil + var walk func(module.Version) error + walk = func(m module.Version) error { + _, ok := reqCache[m] + if ok { + return nil + } + required, err := reqs.Required(m) + if err != nil { + return err + } + reqCache[m] = required + for _, m1 := range required { + if err := walk(m1); err != nil { + return err + } + } + postorder = append(postorder, m) + return nil + } + for _, m := range list { + if err := walk(m); err != nil { + return nil, err + } + } + + // Walk modules in reverse post-order, only adding those not implied already. + have := map[string]string{} + walk = func(m module.Version) error { + if v, ok := have[m.Path]; ok && reqs.Max(m.Version, v) == v { + return nil + } + have[m.Path] = m.Version + for _, m1 := range reqCache[m] { + walk(m1) + } + return nil + } + max := map[string]string{} + for _, m := range list { + if v, ok := max[m.Path]; ok { + max[m.Path] = reqs.Max(m.Version, v) + } else { + max[m.Path] = m.Version + } + } + // First walk the base modules that must be listed. + var min []module.Version + for _, path := range base { + m := module.Version{Path: path, Version: max[path]} + min = append(min, m) + walk(m) + } + // Now the reverse postorder to bring in anything else. + for i := len(postorder) - 1; i >= 0; i-- { + m := postorder[i] + if max[m.Path] != m.Version { + // Older version. + continue + } + if have[m.Path] != m.Version { + min = append(min, m) + walk(m) + } + } + sort.Slice(min, func(i, j int) bool { + return min[i].Path < min[j].Path + }) + return min, nil +} + +// 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) { + return buildList(target, reqs, func(m module.Version) module.Version { + if m.Path == target.Path { + return target + } + + latest, err := reqs.Upgrade(m) + if err != nil { + panic(err) // TODO + } + m.Version = latest.Version + return m + }) +} + +// 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) { + list, err := reqs.Required(target) + if err != nil { + panic(err) // TODO + } + // TODO: Maybe if an error is given, + // rerun with BuildList(upgrade[0], reqs) etc + // to find which ones are the buggy ones. + list = append([]module.Version(nil), list...) + list = append(list, upgrade...) + return BuildList(target, &override{target, list, reqs}) +} + +// Downgrade returns a build list for the target module +// in which the given additional modules are downgraded. +// +// 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) + if err != nil { + panic(err) // TODO + } + max := make(map[string]string) + for _, r := range list { + max[r.Path] = r.Version + } + for _, d := range downgrade { + if v, ok := max[d.Path]; !ok || reqs.Max(v, d.Version) != d.Version { + max[d.Path] = d.Version + } + } + + var ( + added = make(map[module.Version]bool) + rdeps = make(map[module.Version][]module.Version) + excluded = make(map[module.Version]bool) + ) + var exclude func(module.Version) + exclude = func(m module.Version) { + if excluded[m] { + return + } + excluded[m] = true + for _, p := range rdeps[m] { + exclude(p) + } + } + var add func(module.Version) + add = func(m module.Version) { + if added[m] { + return + } + added[m] = true + if v, ok := max[m.Path]; ok && reqs.Max(m.Version, v) != v { + exclude(m) + return + } + list, err := reqs.Required(m) + if err != nil { + panic(err) // TODO + } + for _, r := range list { + add(r) + if excluded[r] { + exclude(m) + return + } + rdeps[r] = append(rdeps[r], m) + } + } + + var out []module.Version + out = append(out, target) +List: + for _, r := range list { + add(r) + for excluded[r] { + p, err := reqs.Previous(r) + if err != nil { + return nil, err // TODO + } + // If the target version is a pseudo-version, it may not be + // included when iterating over prior versions using reqs.Previous. + // Insert it into the right place in the iteration. + // If v is excluded, p should be returned again by reqs.Previous on the next iteration. + if v := max[r.Path]; reqs.Max(v, r.Version) != v && reqs.Max(p.Version, v) != p.Version { + p.Version = v + } + if p.Version == "none" { + continue List + } + add(p) + r = p + } + out = append(out, r) + } + + return out, nil +} + +type override struct { + target module.Version + list []module.Version + Reqs +} + +func (r *override) Required(m module.Version) ([]module.Version, error) { + if m == r.target { + return r.list, nil + } + return r.Reqs.Required(m) +} diff --git a/libgo/go/cmd/go/internal/mvs/mvs_test.go b/libgo/go/cmd/go/internal/mvs/mvs_test.go new file mode 100644 index 00000000000..2a27dfb2889 --- /dev/null +++ b/libgo/go/cmd/go/internal/mvs/mvs_test.go @@ -0,0 +1,473 @@ +// 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 mvs + +import ( + "reflect" + "strings" + "testing" + + "cmd/go/internal/module" +) + +var tests = ` +# Scenario from blog. +name: blog +A: B1 C2 +B1: D3 +C1: D2 +C2: D4 +C3: D5 +C4: G1 +D2: E1 +D3: E2 +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 G1 +upgrade A C4: A B1 C4 D4 E2 F1 G1 +downgrade A2 D2: A2 C4 D2 + +name: trim +A: B1 C2 +B1: D3 +C2: B2 +B2: +build A: A B2 C2 + +# Cross-dependency between D and E. +# No matter how it arises, should get result of merging all build lists via max, +# which leads to including both D2 and E2. + +name: cross1 +A: B C +B: D1 +C: D2 +D1: E2 +D2: E1 +build A: A B C D2 E2 + +name: cross1V +A: B2 C D2 E1 +B1: +B2: D1 +C: D2 +D1: E2 +D2: E1 +build A: A B2 C D2 E2 + +name: cross1U +A: B1 C +B1: +B2: D1 +C: D2 +D1: E2 +D2: E1 +build A: A B1 C D2 E1 +upgrade A B2: A B2 C D2 E2 + +name: cross1R +A: B C +B: D2 +C: D1 +D1: E2 +D2: E1 +build A: A B C D2 E2 + +name: cross1X +A: B C +B: D1 E2 +C: D2 +D1: E2 +D2: E1 +build A: A B C D2 E2 + +name: cross2 +A: B D2 +B: D1 +D1: E2 +D2: E1 +build A: A B D2 E2 + +name: cross2X +A: B D2 +B: D1 E2 +C: D2 +D1: E2 +D2: E1 +build A: A B D2 E2 + +name: cross3 +A: B D2 E1 +B: D1 +D1: E2 +D2: E1 +build A: A B D2 E2 + +name: cross3X +A: B D2 E1 +B: D1 E2 +D1: E2 +D2: E1 +build A: A B D2 E2 + +# Should not get E2 here, because B has been updated +# not to depend on D1 anymore. +name: cross4 +A1: B1 D2 +A2: B2 D2 +B1: D1 +B2: D2 +D1: E2 +D2: E1 +build A1: A1 B1 D2 E2 +build A2: A2 B2 D2 E1 + +# But the upgrade from A1 preserves the E2 dep explicitly. +upgrade A1 B2: A1 B2 D2 E2 +upgradereq A1 B2: B2 E2 + +name: cross5 +A: D1 +D1: E2 +D2: E1 +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 +upgrade A E2: A D2 E2 + +name: cross7 +A: B C +B: D1 +C: E1 +D1: E2 +E1: D2 +build A: A B C D2 E2 + +# Upgrade from B1 to B2 should drop the transitive dep on D. +name: drop +A: B1 C1 +B1: D1 +B2: +C2: +D2: +build A: A B1 C1 D1 +upgrade* A: A B2 C2 + +name: simplify +A: B1 C1 +B1: C2 +C1: D1 +C2: +build A: A B1 C2 + +name: up1 +A: B1 C1 +B1: +B2: +B3: +B4: +B5.hidden: +C2: +C3: +build A: A B1 C1 +upgrade* A: A B4 C3 + +name: up2 +A: B5.hidden C1 +B1: +B2: +B3: +B4: +B5.hidden: +C2: +C3: +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 + +name: down2 +A: B2 E2 +B1: +B2: C2 F2 +C1: +D1: +C2: D2 E2 +D2: B2 +E2: D2 +E1: +F1: +downgrade A F1: A B1 E1 + +name: down3 +A: + +# golang.org/issue/25542. +name: noprev1 +A: B4 C2 +B2.hidden: +C2: +downgrade A B2.hidden: A B2.hidden C2 + +name: noprev2 +A: B4 C2 +B2.hidden: +B1: +C2: +downgrade A B2.hidden: A B2.hidden C2 + +name: noprev3 +A: B4 C2 +B3: +B2.hidden: +C2: +downgrade A B2.hidden: A B2.hidden C2 + +# Cycles involving the target. + +# The target must be the newest version of itself. +name: cycle1 +A: B1 +B1: A1 +B2: A2 +B3: A3 +build A: A B1 +upgrade A B2: A B2 +upgrade* A: A B3 + +# Requirements of older versions of the target +# must not be carried over. +name: cycle2 +A: B1 +A1: C1 +A2: D1 +B1: A1 +B2: A2 +C1: A2 +C2: +D2: +build A: A B1 +upgrade* A: A B2 + +# Requirement minimization. + +name: req1 +A: B1 C1 D1 E1 F1 +B1: C1 E1 F1 +req A: B1 D1 +req A C: B1 C1 D1 + +name: req2 +A: G1 H1 +G1: H1 +H1: G1 +req A: G1 +req A G: G1 +req A H: H1 +` + +func Test(t *testing.T) { + var ( + name string + reqs reqsMap + fns []func(*testing.T) + ) + flush := func() { + if name != "" { + t.Run(name, func(t *testing.T) { + for _, fn := range fns { + fn(t) + } + }) + } + } + m := func(s string) module.Version { + return module.Version{Path: s[:1], Version: s[1:]} + } + ms := func(list []string) []module.Version { + var mlist []module.Version + for _, s := range list { + mlist = append(mlist, m(s)) + } + return mlist + } + checkList := func(t *testing.T, desc string, list []module.Version, err error, val string) { + if err != nil { + t.Fatalf("%s: %v", desc, err) + } + vs := ms(strings.Fields(val)) + if !reflect.DeepEqual(list, vs) { + t.Errorf("%s = %v, want %v", desc, list, vs) + } + } + + for _, line := range strings.Split(tests, "\n") { + line = strings.TrimSpace(line) + if strings.HasPrefix(line, "#") || line == "" { + continue + } + i := strings.Index(line, ":") + if i < 0 { + t.Fatalf("missing colon: %q", line) + } + key := strings.TrimSpace(line[:i]) + val := strings.TrimSpace(line[i+1:]) + if key == "" { + t.Fatalf("missing key: %q", line) + } + kf := strings.Fields(key) + switch kf[0] { + case "name": + if len(kf) != 1 { + t.Fatalf("name takes no arguments: %q", line) + } + flush() + reqs = make(reqsMap) + fns = nil + name = val + continue + case "build": + if len(kf) != 2 { + t.Fatalf("build takes one argument: %q", line) + } + fns = append(fns, func(t *testing.T) { + list, err := BuildList(m(kf[1]), reqs) + checkList(t, key, list, err, val) + }) + continue + case "upgrade*": + if len(kf) != 2 { + t.Fatalf("upgrade* takes one argument: %q", line) + } + fns = append(fns, func(t *testing.T) { + list, err := UpgradeAll(m(kf[1]), reqs) + checkList(t, key, list, err, val) + }) + continue + case "upgradereq": + if len(kf) < 2 { + t.Fatalf("upgrade takes at least one argument: %q", line) + } + fns = append(fns, func(t *testing.T) { + list, err := Upgrade(m(kf[1]), reqs, ms(kf[2:])...) + if err == nil { + list, err = Req(m(kf[1]), list, nil, reqs) + } + checkList(t, key, list, err, val) + }) + continue + case "upgrade": + if len(kf) < 2 { + t.Fatalf("upgrade takes at least one argument: %q", line) + } + fns = append(fns, func(t *testing.T) { + list, err := Upgrade(m(kf[1]), reqs, ms(kf[2:])...) + checkList(t, key, list, err, val) + }) + continue + case "downgrade": + if len(kf) < 2 { + t.Fatalf("downgrade takes at least one argument: %q", line) + } + fns = append(fns, func(t *testing.T) { + list, err := Downgrade(m(kf[1]), reqs, ms(kf[1:])...) + checkList(t, key, list, err, val) + }) + continue + case "req": + if len(kf) < 2 { + t.Fatalf("req takes at least one argument: %q", line) + } + fns = append(fns, func(t *testing.T) { + list, err := BuildList(m(kf[1]), reqs) + if err != nil { + t.Fatal(err) + } + list, err = Req(m(kf[1]), list, kf[2:], reqs) + checkList(t, key, list, err, val) + }) + continue + } + if len(kf) == 1 && 'A' <= key[0] && key[0] <= 'Z' { + var rs []module.Version + for _, f := range strings.Fields(val) { + r := m(f) + if reqs[r] == nil { + reqs[r] = []module.Version{} + } + rs = append(rs, r) + } + reqs[m(key)] = rs + continue + } + t.Fatalf("bad line: %q", line) + } + flush() +} + +type reqsMap map[module.Version][]module.Version + +func (r reqsMap) Max(v1, v2 string) string { + if v1 == "none" || v2 == "" { + return v2 + } + if v2 == "none" || v1 == "" { + return v1 + } + if v1 < v2 { + return v2 + } + return v1 +} + +func (r reqsMap) Upgrade(m module.Version) (module.Version, error) { + var u module.Version + for k := range r { + if k.Path == m.Path && u.Version < k.Version && !strings.HasSuffix(k.Version, ".hidden") { + u = k + } + } + if u.Path == "" { + return module.Version{}, &MissingModuleError{module.Version{Path: m.Path, Version: ""}} + } + return u, nil +} + +func (r reqsMap) Previous(m module.Version) (module.Version, error) { + var p module.Version + for k := range r { + if k.Path == m.Path && p.Version < k.Version && k.Version < m.Version && !strings.HasSuffix(k.Version, ".hidden") { + p = k + } + } + if p.Path == "" { + return module.Version{Path: m.Path, Version: "none"}, nil + } + return p, nil +} + +func (r reqsMap) Required(m module.Version) ([]module.Version, error) { + rr, ok := r[m] + if !ok { + return nil, &MissingModuleError{m} + } + return rr, nil +} diff --git a/libgo/go/cmd/go/internal/par/work.go b/libgo/go/cmd/go/internal/par/work.go new file mode 100644 index 00000000000..a568c86f60b --- /dev/null +++ b/libgo/go/cmd/go/internal/par/work.go @@ -0,0 +1,149 @@ +// 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 par implements parallel execution helpers. +package par + +import ( + "math/rand" + "sync" + "sync/atomic" +) + +// Work manages a set of work items to be executed in parallel, at most once each. +// The items in the set must all be valid map keys. +type Work struct { + f func(interface{}) // function to run for each item + running int // total number of runners + + mu sync.Mutex + added map[interface{}]bool // items added to set + todo []interface{} // items yet to be run + wait sync.Cond // wait when todo is empty + waiting int // number of runners waiting for todo +} + +func (w *Work) init() { + if w.added == nil { + w.added = make(map[interface{}]bool) + } +} + +// Add adds item to the work set, if it hasn't already been added. +func (w *Work) Add(item interface{}) { + w.mu.Lock() + w.init() + if !w.added[item] { + w.added[item] = true + w.todo = append(w.todo, item) + if w.waiting > 0 { + w.wait.Signal() + } + } + w.mu.Unlock() +} + +// Do runs f in parallel on items from the work set, +// with at most n invocations of f running at a time. +// It returns when everything added to the work set has been processed. +// At least one item should have been added to the work set +// before calling Do (or else Do returns immediately), +// but it is allowed for f(item) to add new items to the set. +// Do should only be used once on a given Work. +func (w *Work) Do(n int, f func(item interface{})) { + if n < 1 { + panic("par.Work.Do: n < 1") + } + if w.running >= 1 { + panic("par.Work.Do: already called Do") + } + + w.running = n + w.f = f + w.wait.L = &w.mu + + for i := 0; i < n-1; i++ { + go w.runner() + } + w.runner() +} + +// runner executes work in w until both nothing is left to do +// and all the runners are waiting for work. +// (Then all the runners return.) +func (w *Work) runner() { + for { + // Wait for something to do. + w.mu.Lock() + for len(w.todo) == 0 { + w.waiting++ + if w.waiting == w.running { + // All done. + w.wait.Broadcast() + w.mu.Unlock() + return + } + w.wait.Wait() + w.waiting-- + } + + // Pick something to do at random, + // to eliminate pathological contention + // in case items added at about the same time + // are most likely to contend. + i := rand.Intn(len(w.todo)) + item := w.todo[i] + w.todo[i] = w.todo[len(w.todo)-1] + w.todo = w.todo[:len(w.todo)-1] + w.mu.Unlock() + + w.f(item) + } +} + +// Cache runs an action once per key and caches the result. +type Cache struct { + m sync.Map +} + +type cacheEntry struct { + done uint32 + mu sync.Mutex + result interface{} +} + +// Do calls the function f if and only if Do is being called for the first time with this key. +// No call to Do with a given key returns until the one call to f returns. +// Do returns the value returned by the one call to f. +func (c *Cache) Do(key interface{}, f func() interface{}) interface{} { + entryIface, ok := c.m.Load(key) + if !ok { + entryIface, _ = c.m.LoadOrStore(key, new(cacheEntry)) + } + e := entryIface.(*cacheEntry) + if atomic.LoadUint32(&e.done) == 0 { + e.mu.Lock() + if atomic.LoadUint32(&e.done) == 0 { + e.result = f() + atomic.StoreUint32(&e.done, 1) + } + e.mu.Unlock() + } + return e.result +} + +// Get returns the cached result associated with key. +// It returns nil if there is no such result. +// If the result for key is being computed, Get does not wait for the computation to finish. +func (c *Cache) Get(key interface{}) interface{} { + entryIface, ok := c.m.Load(key) + if !ok { + return nil + } + e := entryIface.(*cacheEntry) + if atomic.LoadUint32(&e.done) == 0 { + return nil + } + return e.result +} diff --git a/libgo/go/cmd/go/internal/par/work_test.go b/libgo/go/cmd/go/internal/par/work_test.go new file mode 100644 index 00000000000..f104bc4106f --- /dev/null +++ b/libgo/go/cmd/go/internal/par/work_test.go @@ -0,0 +1,77 @@ +// 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 par + +import ( + "sync/atomic" + "testing" + "time" +) + +func TestWork(t *testing.T) { + var w Work + + const N = 10000 + n := int32(0) + w.Add(N) + w.Do(100, func(x interface{}) { + atomic.AddInt32(&n, 1) + i := x.(int) + if i >= 2 { + w.Add(i - 1) + w.Add(i - 2) + } + w.Add(i >> 1) + w.Add((i >> 1) ^ 1) + }) + if n != N+1 { + t.Fatalf("ran %d items, expected %d", n, N+1) + } +} + +func TestWorkParallel(t *testing.T) { + for tries := 0; tries < 10; tries++ { + var w Work + const N = 100 + for i := 0; i < N; i++ { + w.Add(i) + } + start := time.Now() + var n int32 + w.Do(N, func(x interface{}) { + time.Sleep(1 * time.Millisecond) + atomic.AddInt32(&n, +1) + }) + if n != N { + t.Fatalf("par.Work.Do did not do all the work") + } + if time.Since(start) < N/2*time.Millisecond { + return + } + } + t.Fatalf("par.Work.Do does not seem to be parallel") +} + +func TestCache(t *testing.T) { + var cache Cache + + n := 1 + v := cache.Do(1, func() interface{} { n++; return n }) + if v != 2 { + t.Fatalf("cache.Do(1) did not run f") + } + v = cache.Do(1, func() interface{} { n++; return n }) + if v != 2 { + t.Fatalf("cache.Do(1) ran f again!") + } + v = cache.Do(2, func() interface{} { n++; return n }) + if v != 3 { + t.Fatalf("cache.Do(2) did not run f") + } + v = cache.Do(1, func() interface{} { n++; return n }) + if v != 2 { + t.Fatalf("cache.Do(1) did not returned saved value from original cache.Do(1)") + } +} diff --git a/libgo/go/cmd/go/internal/run/run.go b/libgo/go/cmd/go/internal/run/run.go index ce24748f4e3..303e6842e7b 100644 --- a/libgo/go/cmd/go/internal/run/run.go +++ b/libgo/go/cmd/go/internal/run/run.go @@ -18,11 +18,13 @@ import ( ) var CmdRun = &base.Command{ - UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]", + UsageLine: "go run [build flags] [-exec xprog] package [arguments...]", Short: "compile and run Go program", Long: ` -Run compiles and runs the main package comprising the named Go source files. -A Go source file is defined to be a file ending in a literal ".go" suffix. +Run compiles and runs the named main Go package. +Typically the package is specified as a list of .go source files, +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'. 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: @@ -34,7 +36,10 @@ for example 'go_nacl_386_exec a.out arguments...'. This allows execution of cross-compiled programs when a simulator or other execution method is available. +The exit status of Run is not the exit status of the compiled binary. + For more about build flags, see 'go help build'. +For more about specifying packages, see 'go help packages'. See also: go build. `, @@ -60,18 +65,33 @@ func runRun(cmd *base.Command, args []string) { for i < len(args) && strings.HasSuffix(args[i], ".go") { i++ } - files, cmdArgs := args[:i], args[i:] - if len(files) == 0 { + var p *load.Package + if i > 0 { + files := args[:i] + for _, file := range files { + if strings.HasSuffix(file, "_test.go") { + // GoFilesPackage is going to assign this to TestGoFiles. + // Reject since it won't be part of the build. + base.Fatalf("go run: cannot run *_test.go files (%s)", file) + } + } + p = load.GoFilesPackage(files) + } else if len(args) > 0 && !strings.HasPrefix(args[0], "-") { + pkgs := load.PackagesAndErrors(args[:1]) + 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")) + } + p = pkgs[0] + i++ + } else { base.Fatalf("go run: no go files listed") } - for _, file := range files { - if strings.HasSuffix(file, "_test.go") { - // GoFilesPackage is going to assign this to TestGoFiles. - // Reject since it won't be part of the build. - base.Fatalf("go run: cannot run *_test.go files (%s)", file) - } - } - p := load.GoFilesPackage(files) + cmdArgs := args[i:] + if p.Error != nil { base.Fatalf("%s", p.Error) } diff --git a/libgo/go/cmd/go/internal/search/search.go b/libgo/go/cmd/go/internal/search/search.go new file mode 100644 index 00000000000..60ae73696bb --- /dev/null +++ b/libgo/go/cmd/go/internal/search/search.go @@ -0,0 +1,505 @@ +// 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 search + +import ( + "cmd/go/internal/base" + "cmd/go/internal/cfg" + "fmt" + "go/build" + "log" + "os" + "path" + "path/filepath" + "regexp" + "strings" +) + +// A Match represents the result of matching a single package pattern. +type Match struct { + Pattern string // the pattern itself + Literal bool // whether it is a literal (no wildcards) + Pkgs []string // matching packages (dirs or import paths) +} + +// MatchPackages returns all the packages that can be found +// under the $GOPATH directories and $GOROOT matching pattern. +// The pattern is either "all" (all packages), "std" (standard packages), +// "cmd" (standard commands), or a path including "...". +func MatchPackages(pattern string) *Match { + m := &Match{ + Pattern: pattern, + Literal: false, + } + match := func(string) bool { return true } + treeCanMatch := func(string) bool { return true } + if !IsMetaPackage(pattern) { + match = MatchPattern(pattern) + treeCanMatch = TreeCanMatchPattern(pattern) + } + + have := map[string]bool{ + "builtin": true, // ignore pseudo-package that exists only for documentation + } + if !cfg.BuildContext.CgoEnabled { + have["runtime/cgo"] = true // ignore during walk + } + + for _, src := range cfg.BuildContext.SrcDirs() { + if (pattern == "std" || pattern == "cmd") && src != cfg.GOROOTsrc { + continue + } + src = filepath.Clean(src) + string(filepath.Separator) + root := src + if pattern == "cmd" { + root += "cmd" + string(filepath.Separator) + } + filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { + if err != nil || path == src { + return nil + } + + want := true + // Avoid .foo, _foo, and testdata directory trees. + _, elem := filepath.Split(path) + if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { + want = false + } + + name := filepath.ToSlash(path[len(src):]) + if pattern == "std" && (!IsStandardImportPath(name) || name == "cmd") { + // The name "std" is only the standard library. + // If the name is cmd, it's the root of the command tree. + want = false + } + if !treeCanMatch(name) { + want = false + } + + if !fi.IsDir() { + if fi.Mode()&os.ModeSymlink != 0 && want { + if target, err := os.Stat(path); err == nil && target.IsDir() { + fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path) + } + } + return nil + } + if !want { + return filepath.SkipDir + } + + if have[name] { + return nil + } + have[name] = true + if !match(name) { + return nil + } + pkg, err := cfg.BuildContext.ImportDir(path, 0) + if err != nil { + if _, noGo := err.(*build.NoGoError); noGo { + return nil + } + } + + // If we are expanding "cmd", skip main + // packages under cmd/vendor. At least as of + // March, 2017, there is one there for the + // vendored pprof tool. + if pattern == "cmd" && strings.HasPrefix(pkg.ImportPath, "cmd/vendor") && pkg.Name == "main" { + return nil + } + + m.Pkgs = append(m.Pkgs, name) + return nil + }) + } + return m +} + +var modRoot string + +func SetModRoot(dir string) { + modRoot = dir +} + +// MatchPackagesInFS is like allPackages but is passed a pattern +// beginning ./ or ../, meaning it should scan the tree rooted +// at the given directory. There are ... in the pattern too. +// (See go help packages for pattern syntax.) +func MatchPackagesInFS(pattern string) *Match { + m := &Match{ + Pattern: pattern, + Literal: false, + } + + // Find directory to begin the scan. + // Could be smarter but this one optimization + // is enough for now, since ... is usually at the + // end of a path. + i := strings.Index(pattern, "...") + dir, _ := path.Split(pattern[:i]) + + // pattern begins with ./ or ../. + // path.Clean will discard the ./ but not the ../. + // We need to preserve the ./ for pattern matching + // and in the returned import paths. + prefix := "" + if strings.HasPrefix(pattern, "./") { + prefix = "./" + } + match := MatchPattern(pattern) + + if modRoot != "" { + abs, err := filepath.Abs(dir) + if err != nil { + base.Fatalf("go: %v", err) + } + if !hasFilepathPrefix(abs, modRoot) { + base.Fatalf("go: pattern %s refers to dir %s, outside module root %s", pattern, abs, modRoot) + return nil + } + } + + filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { + if err != nil || !fi.IsDir() { + return nil + } + top := false + if path == dir { + // filepath.Walk starts at dir and recurses. For the recursive case, + // the path is the result of filepath.Join, which calls filepath.Clean. + // The initial case is not Cleaned, though, so we do this explicitly. + // + // This converts a path like "./io/" to "io". Without this step, running + // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io + // package, because prepending the prefix "./" to the unclean path would + // result in "././io", and match("././io") returns false. + top = true + path = filepath.Clean(path) + } + + // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..". + _, elem := filepath.Split(path) + dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." + if dot || strings.HasPrefix(elem, "_") || elem == "testdata" { + return filepath.SkipDir + } + + if !top && cfg.ModulesEnabled { + // Ignore other modules found in subdirectories. + if _, err := os.Stat(filepath.Join(path, "go.mod")); err == nil { + return filepath.SkipDir + } + } + + name := prefix + filepath.ToSlash(path) + if !match(name) { + return nil + } + + // We keep the directory if we can import it, or if we can't import it + // due to invalid Go source files. This means that directories containing + // parse errors will be built (and fail) instead of being silently skipped + // as not matching the pattern. Go 1.5 and earlier skipped, but that + // behavior means people miss serious mistakes. + // See golang.org/issue/11407. + if p, err := cfg.BuildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) { + if _, noGo := err.(*build.NoGoError); !noGo { + log.Print(err) + } + return nil + } + m.Pkgs = append(m.Pkgs, name) + return nil + }) + return m +} + +// TreeCanMatchPattern(pattern)(name) reports whether +// name or children of name can possibly match pattern. +// Pattern is the same limited glob accepted by matchPattern. +func TreeCanMatchPattern(pattern string) func(name string) bool { + wildCard := false + if i := strings.Index(pattern, "..."); i >= 0 { + wildCard = true + pattern = pattern[:i] + } + return func(name string) bool { + return len(name) <= len(pattern) && hasPathPrefix(pattern, name) || + wildCard && strings.HasPrefix(name, pattern) + } +} + +// MatchPattern(pattern)(name) reports whether +// name matches pattern. Pattern is a limited glob +// pattern in which '...' means 'any string' and there +// is no other special syntax. +// Unfortunately, there are two special cases. Quoting "go help packages": +// +// First, /... at the end of the pattern can match an empty string, +// so that net/... matches both net and packages in its subdirectories, like net/http. +// Second, any slash-separted pattern element containing a wildcard never +// participates in a match of the "vendor" element in the path of a vendored +// package, so that ./... does not match packages in subdirectories of +// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do. +// Note, however, that a directory named vendor that itself contains code +// is not a vendored package: cmd/vendor would be a command named vendor, +// and the pattern cmd/... matches it. +func MatchPattern(pattern string) func(name string) bool { + // Convert pattern to regular expression. + // The strategy for the trailing /... is to nest it in an explicit ? expression. + // The strategy for the vendor exclusion is to change the unmatchable + // vendor strings to a disallowed code point (vendorChar) and to use + // "(anything but that codepoint)*" as the implementation of the ... wildcard. + // This is a bit complicated but the obvious alternative, + // namely a hand-written search like in most shell glob matchers, + // is too easy to make accidentally exponential. + // Using package regexp guarantees linear-time matching. + + const vendorChar = "\x00" + + if strings.Contains(pattern, vendorChar) { + return func(name string) bool { return false } + } + + re := regexp.QuoteMeta(pattern) + re = replaceVendor(re, vendorChar) + switch { + case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`): + re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)` + case re == vendorChar+`/\.\.\.`: + re = `(/vendor|/` + vendorChar + `/\.\.\.)` + case strings.HasSuffix(re, `/\.\.\.`): + re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?` + } + re = strings.Replace(re, `\.\.\.`, `[^`+vendorChar+`]*`, -1) + + reg := regexp.MustCompile(`^` + re + `$`) + + return func(name string) bool { + if strings.Contains(name, vendorChar) { + return false + } + return reg.MatchString(replaceVendor(name, vendorChar)) + } +} + +// replaceVendor returns the result of replacing +// non-trailing vendor path elements in x with repl. +func replaceVendor(x, repl string) string { + if !strings.Contains(x, "vendor") { + return x + } + elem := strings.Split(x, "/") + for i := 0; i < len(elem)-1; i++ { + if elem[i] == "vendor" { + elem[i] = repl + } + } + return strings.Join(elem, "/") +} + +// WarnUnmatched warns about patterns that didn't match any packages. +func WarnUnmatched(matches []*Match) { + for _, m := range matches { + if len(m.Pkgs) == 0 { + fmt.Fprintf(os.Stderr, "go: warning: %q matched no packages\n", m.Pattern) + } + } +} + +// ImportPaths returns the matching paths to use for the given command line. +// It calls ImportPathsQuiet and then WarnUnmatched. +func ImportPaths(patterns []string) []*Match { + matches := ImportPathsQuiet(patterns) + WarnUnmatched(matches) + return matches +} + +// ImportPathsQuiet is like ImportPaths but does not warn about patterns with no matches. +func ImportPathsQuiet(patterns []string) []*Match { + var out []*Match + for _, a := range CleanPatterns(patterns) { + if IsMetaPackage(a) { + out = append(out, MatchPackages(a)) + continue + } + if strings.Contains(a, "...") { + if build.IsLocalImport(a) { + out = append(out, MatchPackagesInFS(a)) + } else { + out = append(out, MatchPackages(a)) + } + continue + } + out = append(out, &Match{Pattern: a, Literal: true, Pkgs: []string{a}}) + } + return out +} + +// CleanPatterns returns the patterns to use for the given +// command line. It canonicalizes the patterns but does not +// evaluate any matches. +func CleanPatterns(patterns []string) []string { + if len(patterns) == 0 { + return []string{"."} + } + var out []string + for _, a := range patterns { + // Arguments are supposed to be import paths, but + // as a courtesy to Windows developers, rewrite \ to / + // in command-line arguments. Handles .\... and so on. + if filepath.Separator == '\\' { + a = strings.Replace(a, `\`, `/`, -1) + } + + // Put argument in canonical form, but preserve leading ./. + if strings.HasPrefix(a, "./") { + a = "./" + path.Clean(a) + if a == "./." { + a = "." + } + } else { + a = path.Clean(a) + } + out = append(out, a) + } + return out +} + +// IsMetaPackage checks if name is a reserved package name that expands to multiple packages. +func IsMetaPackage(name string) bool { + return name == "std" || name == "cmd" || name == "all" +} + +// hasPathPrefix reports whether the path s begins with the +// elements in prefix. +func hasPathPrefix(s, prefix string) bool { + switch { + default: + return false + case len(s) == len(prefix): + return s == prefix + case len(s) > len(prefix): + if prefix != "" && prefix[len(prefix)-1] == '/' { + return strings.HasPrefix(s, prefix) + } + return s[len(prefix)] == '/' && s[:len(prefix)] == prefix + } +} + +// hasFilepathPrefix reports whether the path s begins with the +// elements in prefix. +func hasFilepathPrefix(s, prefix string) bool { + switch { + default: + return false + case len(s) == len(prefix): + return s == prefix + case len(s) > len(prefix): + if prefix != "" && prefix[len(prefix)-1] == filepath.Separator { + return strings.HasPrefix(s, prefix) + } + return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix + } +} + +// IsStandardImportPath reports whether $GOROOT/src/path should be considered +// part of the standard distribution. For historical reasons we allow people to add +// their own code to $GOROOT instead of using $GOPATH, but we assume that +// code will start with a domain name (dot in the first element). +// +// Note that this function is meant to evaluate whether a directory found in GOROOT +// should be treated as part of the standard library. It should not be used to decide +// that a directory found in GOPATH should be rejected: directories in GOPATH +// need not have dots in the first element, and they just take their chances +// with future collisions in the standard library. +func IsStandardImportPath(path string) bool { + i := strings.Index(path, "/") + if i < 0 { + i = len(path) + } + elem := path[:i] + return !strings.Contains(elem, ".") +} + +// IsRelativePath reports whether pattern should be interpreted as a directory +// path relative to the current directory, as opposed to a pattern matching +// import paths. +func IsRelativePath(pattern string) bool { + return strings.HasPrefix(pattern, "./") || strings.HasPrefix(pattern, "../") || pattern == "." || pattern == ".." +} + +// InDir checks whether path is in the file tree rooted at dir. +// 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 + } + xpath, err := filepath.EvalSymlinks(path) + if err != nil || xpath == path { + xpath = "" + } else { + if rel := inDirLex(xpath, dir); rel != "" { + return rel + } + } + + xdir, err := filepath.EvalSymlinks(dir) + if err == nil && xdir != dir { + if rel := inDirLex(path, xdir); rel != "" { + return rel + } + if xpath != "" { + if rel := inDirLex(xpath, xdir); rel != "" { + return rel + } + } + } + return "" +} + +// inDirLex is like inDir but only checks the lexical form of the file names. +// It does not consider symbolic links. +// TODO(rsc): This is a copy of str.HasFilePathPrefix, modified to +// return the suffix. Most uses of str.HasFilePathPrefix should probably +// be calling InDir instead. +func inDirLex(path, dir string) string { + pv := strings.ToUpper(filepath.VolumeName(path)) + dv := strings.ToUpper(filepath.VolumeName(dir)) + path = path[len(pv):] + dir = dir[len(dv):] + switch { + default: + return "" + case pv != dv: + return "" + case len(path) == len(dir): + if path == dir { + return "." + } + return "" + case dir == "": + return path + case len(path) > len(dir): + if dir[len(dir)-1] == filepath.Separator { + if path[:len(dir)] == dir { + return path[len(dir):] + } + return "" + } + if path[len(dir)] == filepath.Separator && path[:len(dir)] == dir { + if len(path) == len(dir)+1 { + return "." + } + return path[len(dir)+1:] + } + return "" + } +} diff --git a/libgo/go/cmd/go/internal/load/match_test.go b/libgo/go/cmd/go/internal/search/search_test.go similarity index 94% rename from libgo/go/cmd/go/internal/load/match_test.go rename to libgo/go/cmd/go/internal/search/search_test.go index b8d67dac742..0bef765fa45 100644 --- a/libgo/go/cmd/go/internal/load/match_test.go +++ b/libgo/go/cmd/go/internal/search/search_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 load +package search import ( "strings" @@ -65,8 +65,8 @@ var matchPatternTests = ` ` func TestMatchPattern(t *testing.T) { - testPatterns(t, "matchPattern", matchPatternTests, func(pattern, name string) bool { - return matchPattern(pattern)(name) + testPatterns(t, "MatchPattern", matchPatternTests, func(pattern, name string) bool { + return MatchPattern(pattern)(name) }) } @@ -106,8 +106,8 @@ var treeCanMatchPatternTests = ` ` func TestTreeCanMatchPattern(t *testing.T) { - testPatterns(t, "treeCanMatchPattern", treeCanMatchPatternTests, func(pattern, name string) bool { - return treeCanMatchPattern(pattern)(name) + testPatterns(t, "TreeCanMatchPattern", treeCanMatchPatternTests, func(pattern, name string) bool { + return TreeCanMatchPattern(pattern)(name) }) } diff --git a/libgo/go/cmd/go/internal/semver/semver.go b/libgo/go/cmd/go/internal/semver/semver.go new file mode 100644 index 00000000000..4af7118e55d --- /dev/null +++ b/libgo/go/cmd/go/internal/semver/semver.go @@ -0,0 +1,388 @@ +// 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 semver implements comparison of semantic version strings. +// In this package, semantic version strings must begin with a leading "v", +// as in "v1.0.0". +// +// The general form of a semantic version string accepted by this package is +// +// vMAJOR[.MINOR[.PATCH[-PRERELEASE][+BUILD]]] +// +// where square brackets indicate optional parts of the syntax; +// MAJOR, MINOR, and PATCH are decimal integers without extra leading zeros; +// PRERELEASE and BUILD are each a series of non-empty dot-separated identifiers +// using only alphanumeric characters and hyphens; and +// all-numeric PRERELEASE identifiers must not have leading zeros. +// +// This package follows Semantic Versioning 2.0.0 (see semver.org) +// with two exceptions. First, it requires the "v" prefix. Second, it recognizes +// vMAJOR and vMAJOR.MINOR (with no prerelease or build suffixes) +// as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0. +package semver + +// parsed returns the parsed form of a semantic version string. +type parsed struct { + major string + minor string + patch string + short string + prerelease string + build string + err string +} + +// IsValid reports whether v is a valid semantic version string. +func IsValid(v string) bool { + _, ok := parse(v) + return ok +} + +// Canonical returns the canonical formatting of the semantic version v. +// It fills in any missing .MINOR or .PATCH and discards build metadata. +// Two semantic versions compare equal only if their canonical formattings +// are identical strings. +// The canonical invalid semantic version is the empty string. +func Canonical(v string) string { + p, ok := parse(v) + if !ok { + return "" + } + if p.build != "" { + return v[:len(v)-len(p.build)] + } + if p.short != "" { + return v + p.short + } + return v +} + +// Major returns the major version prefix of the semantic version v. +// For example, Major("v2.1.0") == "v2". +// If v is an invalid semantic version string, Major returns the empty string. +func Major(v string) string { + pv, ok := parse(v) + if !ok { + return "" + } + return v[:1+len(pv.major)] +} + +// MajorMinor returns the major.minor version prefix of the semantic version v. +// For example, MajorMinor("v2.1.0") == "v2.1". +// If v is an invalid semantic version string, MajorMinor returns the empty string. +func MajorMinor(v string) string { + pv, ok := parse(v) + if !ok { + return "" + } + i := 1 + len(pv.major) + if j := i + 1 + len(pv.minor); j <= len(v) && v[i] == '.' && v[i+1:j] == pv.minor { + return v[:j] + } + return v[:i] + "." + pv.minor +} + +// Prerelease returns the prerelease suffix of the semantic version v. +// For example, Prerelease("v2.1.0-pre+meta") == "-pre". +// If v is an invalid semantic version string, Prerelease returns the empty string. +func Prerelease(v string) string { + pv, ok := parse(v) + if !ok { + return "" + } + return pv.prerelease +} + +// Build returns the build suffix of the semantic version v. +// For example, Build("v2.1.0+meta") == "+meta". +// If v is an invalid semantic version string, Build returns the empty string. +func Build(v string) string { + pv, ok := parse(v) + if !ok { + return "" + } + return pv.build +} + +// Compare returns an integer comparing two versions according to +// according to semantic version precedence. +// The result will be 0 if v == w, -1 if v < w, or +1 if v > w. +// +// An invalid semantic version string is considered less than a valid one. +// All invalid semantic version strings compare equal to each other. +func Compare(v, w string) int { + pv, ok1 := parse(v) + pw, ok2 := parse(w) + if !ok1 && !ok2 { + return 0 + } + if !ok1 { + return -1 + } + if !ok2 { + return +1 + } + if c := compareInt(pv.major, pw.major); c != 0 { + return c + } + if c := compareInt(pv.minor, pw.minor); c != 0 { + return c + } + if c := compareInt(pv.patch, pw.patch); c != 0 { + return c + } + return comparePrerelease(pv.prerelease, pw.prerelease) +} + +// Max canonicalizes its arguments and then returns the version string +// that compares greater. +func Max(v, w string) string { + v = Canonical(v) + w = Canonical(w) + if Compare(v, w) > 0 { + return v + } + return w +} + +func parse(v string) (p parsed, ok bool) { + if v == "" || v[0] != 'v' { + p.err = "missing v prefix" + return + } + p.major, v, ok = parseInt(v[1:]) + if !ok { + p.err = "bad major version" + return + } + if v == "" { + p.minor = "0" + p.patch = "0" + p.short = ".0.0" + return + } + if v[0] != '.' { + p.err = "bad minor prefix" + ok = false + return + } + p.minor, v, ok = parseInt(v[1:]) + if !ok { + p.err = "bad minor version" + return + } + if v == "" { + p.patch = "0" + p.short = ".0" + return + } + if v[0] != '.' { + p.err = "bad patch prefix" + ok = false + return + } + p.patch, v, ok = parseInt(v[1:]) + if !ok { + p.err = "bad patch version" + return + } + if len(v) > 0 && v[0] == '-' { + p.prerelease, v, ok = parsePrerelease(v) + if !ok { + p.err = "bad prerelease" + return + } + } + if len(v) > 0 && v[0] == '+' { + p.build, v, ok = parseBuild(v) + if !ok { + p.err = "bad build" + return + } + } + if v != "" { + p.err = "junk on end" + ok = false + return + } + ok = true + return +} + +func parseInt(v string) (t, rest string, ok bool) { + if v == "" { + return + } + if v[0] < '0' || '9' < v[0] { + return + } + i := 1 + for i < len(v) && '0' <= v[i] && v[i] <= '9' { + i++ + } + if v[0] == '0' && i != 1 { + return + } + return v[:i], v[i:], true +} + +func parsePrerelease(v string) (t, rest string, ok bool) { + // "A pre-release version MAY be denoted by appending a hyphen and + // a series of dot separated identifiers immediately following the patch version. + // Identifiers MUST comprise only ASCII alphanumerics and hyphen [0-9A-Za-z-]. + // Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes." + if v == "" || v[0] != '-' { + return + } + i := 1 + start := 1 + for i < len(v) && v[i] != '+' { + if !isIdentChar(v[i]) && v[i] != '.' { + return + } + if v[i] == '.' { + if start == i || isBadNum(v[start:i]) { + return + } + start = i + 1 + } + i++ + } + if start == i || isBadNum(v[start:i]) { + return + } + return v[:i], v[i:], true +} + +func parseBuild(v string) (t, rest string, ok bool) { + if v == "" || v[0] != '+' { + return + } + i := 1 + start := 1 + for i < len(v) { + if !isIdentChar(v[i]) { + return + } + if v[i] == '.' { + if start == i { + return + } + start = i + 1 + } + i++ + } + if start == i { + return + } + return v[:i], v[i:], true +} + +func isIdentChar(c byte) bool { + return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '-' +} + +func isBadNum(v string) bool { + i := 0 + for i < len(v) && '0' <= v[i] && v[i] <= '9' { + i++ + } + return i == len(v) && i > 1 && v[0] == '0' +} + +func isNum(v string) bool { + i := 0 + for i < len(v) && '0' <= v[i] && v[i] <= '9' { + i++ + } + return i == len(v) +} + +func compareInt(x, y string) int { + if x == y { + return 0 + } + if len(x) < len(y) { + return -1 + } + if len(x) > len(y) { + return +1 + } + if x < y { + return -1 + } else { + return +1 + } +} + +func comparePrerelease(x, y string) int { + // "When major, minor, and patch are equal, a pre-release version has + // lower precedence than a normal version. + // Example: 1.0.0-alpha < 1.0.0. + // Precedence for two pre-release versions with the same major, minor, + // and patch version MUST be determined by comparing each dot separated + // identifier from left to right until a difference is found as follows: + // identifiers consisting of only digits are compared numerically and + // identifiers with letters or hyphens are compared lexically in ASCII + // sort order. Numeric identifiers always have lower precedence than + // non-numeric identifiers. A larger set of pre-release fields has a + // higher precedence than a smaller set, if all of the preceding + // identifiers are equal. + // Example: 1.0.0-alpha < 1.0.0-alpha.1 < 1.0.0-alpha.beta < + // 1.0.0-beta < 1.0.0-beta.2 < 1.0.0-beta.11 < 1.0.0-rc.1 < 1.0.0." + if x == y { + return 0 + } + if x == "" { + return +1 + } + if y == "" { + return -1 + } + for x != "" && y != "" { + x = x[1:] // skip - or . + y = y[1:] // skip - or . + var dx, dy string + dx, x = nextIdent(x) + dy, y = nextIdent(y) + if dx != dy { + ix := isNum(dx) + iy := isNum(dy) + if ix != iy { + if ix { + return -1 + } else { + return +1 + } + } + if ix { + if len(dx) < len(dy) { + return -1 + } + if len(dx) > len(dy) { + return +1 + } + } + if dx < dy { + return -1 + } else { + return +1 + } + } + } + if x == "" { + return -1 + } else { + return +1 + } +} + +func nextIdent(x string) (dx, rest string) { + i := 0 + for i < len(x) && x[i] != '.' { + i++ + } + return x[:i], x[i:] +} diff --git a/libgo/go/cmd/go/internal/semver/semver_test.go b/libgo/go/cmd/go/internal/semver/semver_test.go new file mode 100644 index 00000000000..96b64a58075 --- /dev/null +++ b/libgo/go/cmd/go/internal/semver/semver_test.go @@ -0,0 +1,182 @@ +// 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 semver + +import ( + "strings" + "testing" +) + +var tests = []struct { + in string + out string +}{ + {"bad", ""}, + {"v1-alpha.beta.gamma", ""}, + {"v1-pre", ""}, + {"v1+meta", ""}, + {"v1-pre+meta", ""}, + {"v1.2-pre", ""}, + {"v1.2+meta", ""}, + {"v1.2-pre+meta", ""}, + {"v1.0.0-alpha", "v1.0.0-alpha"}, + {"v1.0.0-alpha.1", "v1.0.0-alpha.1"}, + {"v1.0.0-alpha.beta", "v1.0.0-alpha.beta"}, + {"v1.0.0-beta", "v1.0.0-beta"}, + {"v1.0.0-beta.2", "v1.0.0-beta.2"}, + {"v1.0.0-beta.11", "v1.0.0-beta.11"}, + {"v1.0.0-rc.1", "v1.0.0-rc.1"}, + {"v1", "v1.0.0"}, + {"v1.0", "v1.0.0"}, + {"v1.0.0", "v1.0.0"}, + {"v1.2", "v1.2.0"}, + {"v1.2.0", "v1.2.0"}, + {"v1.2.3-456", "v1.2.3-456"}, + {"v1.2.3-456.789", "v1.2.3-456.789"}, + {"v1.2.3-456-789", "v1.2.3-456-789"}, + {"v1.2.3-456a", "v1.2.3-456a"}, + {"v1.2.3-pre", "v1.2.3-pre"}, + {"v1.2.3-pre+meta", "v1.2.3-pre"}, + {"v1.2.3-pre.1", "v1.2.3-pre.1"}, + {"v1.2.3-zzz", "v1.2.3-zzz"}, + {"v1.2.3", "v1.2.3"}, + {"v1.2.3+meta", "v1.2.3"}, + {"v1.2.3+meta-pre", "v1.2.3"}, +} + +func TestIsValid(t *testing.T) { + for _, tt := range tests { + ok := IsValid(tt.in) + if ok != (tt.out != "") { + t.Errorf("IsValid(%q) = %v, want %v", tt.in, ok, !ok) + } + } +} + +func TestCanonical(t *testing.T) { + for _, tt := range tests { + out := Canonical(tt.in) + if out != tt.out { + t.Errorf("Canonical(%q) = %q, want %q", tt.in, out, tt.out) + } + } +} + +func TestMajor(t *testing.T) { + for _, tt := range tests { + out := Major(tt.in) + want := "" + if i := strings.Index(tt.out, "."); i >= 0 { + want = tt.out[:i] + } + if out != want { + t.Errorf("Major(%q) = %q, want %q", tt.in, out, want) + } + } +} + +func TestMajorMinor(t *testing.T) { + for _, tt := range tests { + out := MajorMinor(tt.in) + var want string + if tt.out != "" { + want = tt.in + if i := strings.Index(want, "+"); i >= 0 { + want = want[:i] + } + if i := strings.Index(want, "-"); i >= 0 { + want = want[:i] + } + switch strings.Count(want, ".") { + case 0: + want += ".0" + case 1: + // ok + case 2: + want = want[:strings.LastIndex(want, ".")] + } + } + if out != want { + t.Errorf("MajorMinor(%q) = %q, want %q", tt.in, out, want) + } + } +} + +func TestPrerelease(t *testing.T) { + for _, tt := range tests { + pre := Prerelease(tt.in) + var want string + if tt.out != "" { + if i := strings.Index(tt.out, "-"); i >= 0 { + want = tt.out[i:] + } + } + if pre != want { + t.Errorf("Prerelease(%q) = %q, want %q", tt.in, pre, want) + } + } +} + +func TestBuild(t *testing.T) { + for _, tt := range tests { + build := Build(tt.in) + var want string + if tt.out != "" { + if i := strings.Index(tt.in, "+"); i >= 0 { + want = tt.in[i:] + } + } + if build != want { + t.Errorf("Build(%q) = %q, want %q", tt.in, build, want) + } + } +} + +func TestCompare(t *testing.T) { + for i, ti := range tests { + for j, tj := range tests { + cmp := Compare(ti.in, tj.in) + var want int + if ti.out == tj.out { + want = 0 + } else if i < j { + want = -1 + } else { + want = +1 + } + if cmp != want { + t.Errorf("Compare(%q, %q) = %d, want %d", ti.in, tj.in, cmp, want) + } + } + } +} + +func TestMax(t *testing.T) { + for i, ti := range tests { + for j, tj := range tests { + max := Max(ti.in, tj.in) + want := Canonical(ti.in) + if i < j { + want = Canonical(tj.in) + } + if max != want { + t.Errorf("Max(%q, %q) = %q, want %q", ti.in, tj.in, max, want) + } + } + } +} + +var ( + v1 = "v1.0.0+metadata-dash" + v2 = "v1.0.0+metadata-dash1" +) + +func BenchmarkCompare(b *testing.B) { + for i := 0; i < b.N; i++ { + if Compare(v1, v2) != 0 { + b.Fatalf("bad compare") + } + } +} diff --git a/libgo/go/cmd/go/internal/str/path.go b/libgo/go/cmd/go/internal/str/path.go index 84ca9d581e9..a9b4d759a6b 100644 --- a/libgo/go/cmd/go/internal/str/path.go +++ b/libgo/go/cmd/go/internal/str/path.go @@ -9,8 +9,25 @@ import ( "strings" ) -// HasFilePathPrefix reports whether the filesystem path s begins with the -// elements in prefix. +// HasPath reports whether the slash-separated path s +// begins with the elements in prefix. +func HasPathPrefix(s, prefix string) bool { + if len(s) == len(prefix) { + return s == prefix + } + if prefix == "" { + return true + } + if len(s) > len(prefix) { + if prefix[len(prefix)-1] == '/' || s[len(prefix)] == '/' { + return s[:len(prefix)] == prefix + } + } + return false +} + +// HasFilePathPrefix reports whether the filesystem path s +// begins with the elements in prefix. func HasFilePathPrefix(s, prefix string) bool { sv := strings.ToUpper(filepath.VolumeName(s)) pv := strings.ToUpper(filepath.VolumeName(prefix)) @@ -23,8 +40,10 @@ func HasFilePathPrefix(s, prefix string) bool { return false case len(s) == len(prefix): return s == prefix + case prefix == "": + return true case len(s) > len(prefix): - if prefix != "" && prefix[len(prefix)-1] == filepath.Separator { + if prefix[len(prefix)-1] == filepath.Separator { return strings.HasPrefix(s, prefix) } return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix diff --git a/libgo/go/cmd/go/internal/test/cover.go b/libgo/go/cmd/go/internal/test/cover.go index 12538b46564..9841791552d 100644 --- a/libgo/go/cmd/go/internal/test/cover.go +++ b/libgo/go/cmd/go/internal/test/cover.go @@ -23,7 +23,7 @@ var coverMerge struct { // Using this function clears the profile in case it existed from a previous run, // or in case it doesn't exist and the test is going to fail to create it (or not run). func initCoverProfile() { - if testCoverProfile == "" { + if testCoverProfile == "" || testC { return } if !filepath.IsAbs(testCoverProfile) && testOutputDir != "" { diff --git a/libgo/go/cmd/go/internal/test/test.go b/libgo/go/cmd/go/internal/test/test.go index 5adb7df7c48..a089f1b134a 100644 --- a/libgo/go/cmd/go/internal/test/test.go +++ b/libgo/go/cmd/go/internal/test/test.go @@ -9,11 +9,7 @@ import ( "crypto/sha256" "errors" "fmt" - "go/ast" "go/build" - "go/doc" - "go/parser" - "go/token" "io" "io/ioutil" "os" @@ -25,15 +21,13 @@ import ( "strconv" "strings" "sync" - "text/template" "time" - "unicode" - "unicode/utf8" "cmd/go/internal/base" "cmd/go/internal/cache" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/modload" "cmd/go/internal/str" "cmd/go/internal/work" "cmd/internal/test2json" @@ -44,7 +38,7 @@ func init() { CmdTest.Run = runTest } -const testUsage = "test [build/test flags] [packages] [build/test flags & test binary flags]" +const testUsage = "go test [build/test flags] [packages] [build/test flags & test binary flags]" var CmdTest = &base.Command{ CustomFlags: true, @@ -76,9 +70,12 @@ to hold ancillary data needed by the tests. As part of building a test binary, go test runs go vet on the package and its test source files to identify significant problems. If go vet -finds any problems, go test reports those and does not run the test binary. -Only a high-confidence subset of the default go vet checks are used. -To disable the running of go vet, use the -vet=off flag. +finds any problems, go test reports those and does not run the test +binary. Only a high-confidence subset of the default go vet checks are +used. That subset is: 'atomic', 'bool', 'buildtags', 'nilfunc', and +'printf'. You can see the documentation for these and other vet tests +via "go doc cmd/vet". To disable the running of go vet, use the +-vet=off flag. All test output and summary lines are printed to the go command's standard output, even if the test printed them to its own standard @@ -172,7 +169,7 @@ flags are also accessible by 'go test'. // Usage prints the usage message for 'go test -h' and exits. func Usage() { - os.Stderr.WriteString(testUsage + "\n\n" + + os.Stderr.WriteString("usage: " + testUsage + "\n\n" + strings.TrimSpace(testFlag1) + "\n\n\t" + strings.TrimSpace(testFlag2) + "\n") os.Exit(2) @@ -328,14 +325,13 @@ profile the tests during execution: Writes test binary as -c would. -memprofile mem.out - Write a memory profile to the file after all tests have passed. + Write an allocation profile to the file after all tests have passed. Writes test binary as -c would. -memprofilerate n - Enable more precise (and expensive) memory profiles by setting - runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'. - To profile all memory allocations, use -test.memprofilerate=1 - and pass --alloc_space flag to the pprof tool. + Enable more precise (and expensive) memory allocation profiles by + setting runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'. + To profile all memory allocations, use -test.memprofilerate=1. -mutexprofile mutex.out Write a mutex contention profile to the specified file @@ -385,6 +381,12 @@ flag not known to the go test command. Continuing the example above, the package list would have to appear before -myflag, but could appear on either side of -v. +When 'go test' runs in package list mode, 'go test' caches successful +package test results to avoid unnecessary repeated running of tests. To +disable test caching, use any test flag or argument other than the +cacheable flags. The idiomatic way to disable test caching explicitly +is to use -count=1. + To keep an argument for a test binary from being interpreted as a known flag or a package name, use -args (see 'go help test') which passes the remainder of the command line through to the test binary @@ -499,13 +501,6 @@ var ( testCacheExpire time.Time // ignore cached test results before this time ) -var testMainDeps = []string{ - // Dependencies for testmain. - "os", - "testing", - "testing/internal/testdeps", -} - // testVetFlags is the list of flags to pass to vet when invoked automatically during go test. var testVetFlags = []string{ // TODO(rsc): Decide which tests are enabled by default. @@ -533,6 +528,8 @@ var testVetFlags = []string{ } func runTest(cmd *base.Command, args []string) { + modload.LoadTests = true + pkgArgs, testArgs = testFlags(args) work.FindExecCmd() // initialize cached result @@ -597,7 +594,7 @@ func runTest(cmd *base.Command, args []string) { cfg.BuildV = testV deps := make(map[string]bool) - for _, dep := range testMainDeps { + for _, dep := range load.TestMainDeps { deps[dep] = true } @@ -656,7 +653,7 @@ func runTest(cmd *base.Command, args []string) { } // Select for coverage all dependencies matching the testCoverPaths patterns. - for _, p := range load.PackageList(pkgs) { + for _, p := range load.GetTestPackageList(pkgs) { haveMatch := false for i := range testCoverPaths { if match[i](p) { @@ -704,7 +701,7 @@ func runTest(cmd *base.Command, args []string) { coverFiles = append(coverFiles, p.GoFiles...) coverFiles = append(coverFiles, p.CgoFiles...) coverFiles = append(coverFiles, p.TestGoFiles...) - p.Internal.CoverVars = declareCoverVars(p.ImportPath, coverFiles...) + p.Internal.CoverVars = declareCoverVars(p, coverFiles...) if testCover && testCoverMode == "atomic" { ensureImport(p, "sync/atomic") } @@ -721,16 +718,13 @@ func runTest(cmd *base.Command, args []string) { buildTest, runTest, printTest, err := builderTest(&b, p) if err != nil { str := err.Error() - if strings.HasPrefix(str, "\n") { - str = str[1:] - } - failed := fmt.Sprintf("FAIL\t%s [setup failed]\n", p.ImportPath) - + str = strings.TrimPrefix(str, "\n") if p.ImportPath != "" { - base.Errorf("# %s\n%s\n%s", p.ImportPath, str, failed) + base.Errorf("# %s\n%s", p.ImportPath, str) } else { - base.Errorf("%s\n%s", str, failed) + base.Errorf("%s", str) } + fmt.Printf("FAIL\t%s [setup failed]\n", p.ImportPath) continue } builds = append(builds, buildTest) @@ -798,14 +792,20 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin } // Build Package structs describing: + // pmain - pkg.test binary // ptest - package + test files // pxtest - package of external test files - // pmain - pkg.test binary - var ptest, pxtest, pmain *load.Package - - localCover := testCover && testCoverPaths == nil - - ptest, pxtest, err = load.GetTestPackagesFor(p, localCover || p.Name == "main") + var cover *load.TestCover + if testCover { + cover = &load.TestCover{ + Mode: testCoverMode, + Local: testCover && testCoverPaths == nil, + Pkgs: testCoverPkgs, + Paths: testCoverPaths, + DeclVars: declareCoverVars, + } + } + pmain, ptest, pxtest, err := load.GetTestPackagesFor(p, cover) if err != nil { return nil, nil, nil, err } @@ -822,116 +822,18 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin } testBinary := elem + ".test" - // Should we apply coverage analysis locally, - // only for this package and only for this test? - // Yes, if -cover is on but -coverpkg has not specified - // a list of packages for global coverage. - if localCover { - ptest.Internal.CoverMode = testCoverMode - var coverFiles []string - coverFiles = append(coverFiles, ptest.GoFiles...) - coverFiles = append(coverFiles, ptest.CgoFiles...) - ptest.Internal.CoverVars = declareCoverVars(ptest.ImportPath, coverFiles...) - } - testDir := b.NewObjdir() if err := b.Mkdir(testDir); err != nil { return nil, nil, nil, err } - // Action for building pkg.test. - pmain = &load.Package{ - PackagePublic: load.PackagePublic{ - Name: "main", - Dir: testDir, - GoFiles: []string{"_testmain.go"}, - ImportPath: p.ImportPath + " (testmain)", - Root: p.Root, - }, - Internal: load.PackageInternal{ - Build: &build.Package{Name: "main"}, - OmitDebug: !testC && !testNeedBinary, - - Asmflags: p.Internal.Asmflags, - Gcflags: p.Internal.Gcflags, - Ldflags: p.Internal.Ldflags, - Gccgoflags: p.Internal.Gccgoflags, - }, - } - - // The generated main also imports testing, regexp, and os. - // Also the linker introduces implicit dependencies reported by LinkerDeps. - var stk load.ImportStack - stk.Push("testmain") - deps := testMainDeps // cap==len, so safe for append - for _, d := range load.LinkerDeps(p) { - deps = append(deps, d) - } - for _, dep := range deps { - if dep == ptest.ImportPath { - pmain.Internal.Imports = append(pmain.Internal.Imports, ptest) - } else { - p1 := load.LoadImport(dep, "", nil, &stk, nil, 0) - if p1.Error != nil { - return nil, nil, nil, p1.Error - } - pmain.Internal.Imports = append(pmain.Internal.Imports, p1) - } - } - - if testCoverPkgs != nil { - // Add imports, but avoid duplicates. - seen := map[*load.Package]bool{p: true, ptest: true} - for _, p1 := range pmain.Internal.Imports { - seen[p1] = true - } - for _, p1 := range testCoverPkgs { - if !seen[p1] { - seen[p1] = true - pmain.Internal.Imports = append(pmain.Internal.Imports, p1) - } - } - } - - // Do initial scan for metadata needed for writing _testmain.go - // Use that metadata to update the list of imports for package main. - // The list of imports is used by recompileForTest and by the loop - // afterward that gathers t.Cover information. - t, err := loadTestFuncs(ptest) - if err != nil { - return nil, nil, nil, err - } - if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 { - pmain.Internal.Imports = append(pmain.Internal.Imports, ptest) - t.ImportTest = true - } - if pxtest != nil { - pmain.Internal.Imports = append(pmain.Internal.Imports, pxtest) - t.ImportXtest = true - } - - if ptest != p { - // We have made modifications to the package p being tested - // and are rebuilding p (as ptest). - // Arrange to rebuild all packages q such that - // the test depends on q and q depends on p. - // This makes sure that q sees the modifications to p. - // Strictly speaking, the rebuild is only necessary if the - // modifications to p change its export metadata, but - // determining that is a bit tricky, so we rebuild always. - recompileForTest(pmain, p, ptest, pxtest) - } - - for _, cp := range pmain.Internal.Imports { - if len(cp.Internal.CoverVars) > 0 { - t.Cover = append(t.Cover, coverInfo{cp, cp.Internal.CoverVars}) - } - } + pmain.Dir = testDir + pmain.Internal.OmitDebug = !testC && !testNeedBinary if !cfg.BuildN { // writeTestmain writes _testmain.go, // using the test description gathered in t. - if err := writeTestmain(testDir+"_testmain.go", t); err != nil { + if err := ioutil.WriteFile(testDir+"_testmain.go", *pmain.Internal.TestmainGo, 0666); err != nil { return nil, nil, nil, err } } @@ -993,8 +895,10 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin } runAction = installAction // make sure runAction != nil even if not running test } + var vetRunAction *work.Action if testC { printAction = &work.Action{Mode: "test print (nop)", Package: p, Deps: []*work.Action{runAction}} // nop + vetRunAction = printAction } else { // run test c := new(runCache) @@ -1007,12 +911,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin TryCache: c.tryCache, Objdir: testDir, } - if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 { - addTestVet(b, ptest, runAction, installAction) - } - if pxtest != nil { - addTestVet(b, pxtest, runAction, installAction) - } + vetRunAction = runAction cleanAction = &work.Action{ Mode: "test clean", Func: builderCleanTest, @@ -1029,6 +928,14 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin IgnoreFail: true, // print even if test failed } } + + if len(ptest.GoFiles)+len(ptest.CgoFiles) > 0 { + addTestVet(b, ptest, vetRunAction, installAction) + } + if pxtest != nil { + addTestVet(b, pxtest, vetRunAction, installAction) + } + if installAction != nil { if runAction != installAction { installAction.Deps = append(installAction.Deps, runAction) @@ -1057,44 +964,6 @@ func addTestVet(b *work.Builder, p *load.Package, runAction, installAction *work } } -func recompileForTest(pmain, preal, ptest, pxtest *load.Package) { - // The "test copy" of preal is ptest. - // For each package that depends on preal, make a "test copy" - // that depends on ptest. And so on, up the dependency tree. - testCopy := map[*load.Package]*load.Package{preal: ptest} - for _, p := range load.PackageList([]*load.Package{pmain}) { - if p == preal { - continue - } - // Copy on write. - didSplit := p == pmain || p == pxtest - split := func() { - if didSplit { - return - } - didSplit = true - if testCopy[p] != nil { - panic("recompileForTest loop") - } - p1 := new(load.Package) - testCopy[p] = p1 - *p1 = *p - p1.Internal.Imports = make([]*load.Package, len(p.Internal.Imports)) - copy(p1.Internal.Imports, p.Internal.Imports) - p = p1 - p.Target = "" - } - - // Update p.Internal.Imports to use test copies. - for i, imp := range p.Internal.Imports { - if p1 := testCopy[imp]; p1 != nil && p1 != imp { - split() - p.Internal.Imports[i] = p1 - } - } - } -} - // isTestFile reports whether the source file is a set of tests and should therefore // be excluded from coverage analysis. func isTestFile(file string) bool { @@ -1104,7 +973,7 @@ func isTestFile(file string) bool { // declareCoverVars attaches the required cover variables names // to the files, to be used when annotating the files. -func declareCoverVars(importPath string, files ...string) map[string]*load.CoverVar { +func declareCoverVars(p *load.Package, files ...string) map[string]*load.CoverVar { coverVars := make(map[string]*load.CoverVar) coverIndex := 0 // We create the cover counters as new top-level variables in the package. @@ -1113,14 +982,25 @@ func declareCoverVars(importPath string, files ...string) map[string]*load.Cover // so we append 12 hex digits from the SHA-256 of the import path. // The point is only to avoid accidents, not to defeat users determined to // break things. - sum := sha256.Sum256([]byte(importPath)) + sum := sha256.Sum256([]byte(p.ImportPath)) h := fmt.Sprintf("%x", sum[:6]) for _, file := range files { if isTestFile(file) { continue } + // For a package that is "local" (imported via ./ import or command line, outside GOPATH), + // we record the full path to the file name. + // Otherwise we record the import path, then a forward slash, then the file name. + // This makes profiles within GOPATH file system-independent. + // These names appear in the cmd/cover HTML interface. + var longFile string + if p.Internal.Local { + longFile = filepath.Join(p.Dir, file) + } else { + longFile = path.Join(p.ImportPath, file) + } coverVars[file] = &load.CoverVar{ - File: filepath.Join(importPath, file), + File: longFile, Var: fmt.Sprintf("GoCover_%d_%x", coverIndex, h), } coverIndex++ @@ -1538,7 +1418,7 @@ func computeTestInputsID(a *work.Action, testlog []byte) (cache.ActionID, error) fmt.Fprintf(h, "env %s %x\n", name, hashGetenv(name)) case "chdir": pwd = name // always absolute - fmt.Fprintf(h, "cbdir %s %x\n", name, hashStat(name)) + fmt.Fprintf(h, "chdir %s %x\n", name, hashStat(name)) case "stat": if !filepath.IsAbs(name) { name = filepath.Join(pwd, name) @@ -1746,310 +1626,3 @@ func builderNoTest(b *work.Builder, a *work.Action) error { fmt.Fprintf(stdout, "? \t%s\t[no test files]\n", a.Package.ImportPath) return nil } - -// isTestFunc tells whether fn has the type of a testing function. arg -// specifies the parameter type we look for: B, M or T. -func isTestFunc(fn *ast.FuncDecl, arg string) bool { - if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 || - fn.Type.Params.List == nil || - len(fn.Type.Params.List) != 1 || - len(fn.Type.Params.List[0].Names) > 1 { - return false - } - ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr) - if !ok { - return false - } - // We can't easily check that the type is *testing.M - // because we don't know how testing has been imported, - // but at least check that it's *M or *something.M. - // Same applies for B and T. - if name, ok := ptr.X.(*ast.Ident); ok && name.Name == arg { - return true - } - if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == arg { - return true - } - return false -} - -// isTest tells whether name looks like a test (or benchmark, according to prefix). -// It is a Test (say) if there is a character after Test that is not a lower-case letter. -// We don't want TesticularCancer. -func isTest(name, prefix string) bool { - if !strings.HasPrefix(name, prefix) { - return false - } - if len(name) == len(prefix) { // "Test" is ok - return true - } - rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) - return !unicode.IsLower(rune) -} - -type coverInfo struct { - Package *load.Package - Vars map[string]*load.CoverVar -} - -// loadTestFuncs returns the testFuncs describing the tests that will be run. -func loadTestFuncs(ptest *load.Package) (*testFuncs, error) { - t := &testFuncs{ - Package: ptest, - } - for _, file := range ptest.TestGoFiles { - if err := t.load(filepath.Join(ptest.Dir, file), "_test", &t.ImportTest, &t.NeedTest); err != nil { - return nil, err - } - } - for _, file := range ptest.XTestGoFiles { - if err := t.load(filepath.Join(ptest.Dir, file), "_xtest", &t.ImportXtest, &t.NeedXtest); err != nil { - return nil, err - } - } - return t, nil -} - -// writeTestmain writes the _testmain.go file for t to the file named out. -func writeTestmain(out string, t *testFuncs) error { - f, err := os.Create(out) - if err != nil { - return err - } - defer f.Close() - - if err := testmainTmpl.Execute(f, t); err != nil { - return err - } - - return nil -} - -type testFuncs struct { - Tests []testFunc - Benchmarks []testFunc - Examples []testFunc - TestMain *testFunc - Package *load.Package - ImportTest bool - NeedTest bool - ImportXtest bool - NeedXtest bool - Cover []coverInfo -} - -func (t *testFuncs) CoverMode() string { - return testCoverMode -} - -func (t *testFuncs) CoverEnabled() bool { - return testCover -} - -// ImportPath returns the import path of the package being tested, if it is within GOPATH. -// This is printed by the testing package when running benchmarks. -func (t *testFuncs) ImportPath() string { - pkg := t.Package.ImportPath - if strings.HasPrefix(pkg, "_/") { - return "" - } - if pkg == "command-line-arguments" { - return "" - } - return pkg -} - -// Covered returns a string describing which packages are being tested for coverage. -// If the covered package is the same as the tested package, it returns the empty string. -// Otherwise it is a comma-separated human-readable list of packages beginning with -// " in", ready for use in the coverage message. -func (t *testFuncs) Covered() string { - if testCoverPaths == nil { - return "" - } - return " in " + strings.Join(testCoverPaths, ", ") -} - -// Tested returns the name of the package being tested. -func (t *testFuncs) Tested() string { - return t.Package.Name -} - -type testFunc struct { - Package string // imported package name (_test or _xtest) - Name string // function name - Output string // output, for examples - Unordered bool // output is allowed to be unordered. -} - -var testFileSet = token.NewFileSet() - -func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error { - f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments) - if err != nil { - return base.ExpandScanner(err) - } - for _, d := range f.Decls { - n, ok := d.(*ast.FuncDecl) - if !ok { - continue - } - if n.Recv != nil { - continue - } - name := n.Name.String() - switch { - case name == "TestMain": - if isTestFunc(n, "T") { - t.Tests = append(t.Tests, testFunc{pkg, name, "", false}) - *doImport, *seen = true, true - continue - } - err := checkTestFunc(n, "M") - if err != nil { - return err - } - if t.TestMain != nil { - return errors.New("multiple definitions of TestMain") - } - t.TestMain = &testFunc{pkg, name, "", false} - *doImport, *seen = true, true - case isTest(name, "Test"): - err := checkTestFunc(n, "T") - if err != nil { - return err - } - t.Tests = append(t.Tests, testFunc{pkg, name, "", false}) - *doImport, *seen = true, true - case isTest(name, "Benchmark"): - err := checkTestFunc(n, "B") - if err != nil { - return err - } - t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false}) - *doImport, *seen = true, true - } - } - ex := doc.Examples(f) - sort.Slice(ex, func(i, j int) bool { return ex[i].Order < ex[j].Order }) - for _, e := range ex { - *doImport = true // import test file whether executed or not - if e.Output == "" && !e.EmptyOutput { - // Don't run examples with no output. - continue - } - t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output, e.Unordered}) - *seen = true - } - return nil -} - -func checkTestFunc(fn *ast.FuncDecl, arg string) error { - if !isTestFunc(fn, arg) { - name := fn.Name.String() - pos := testFileSet.Position(fn.Pos()) - return fmt.Errorf("%s: wrong signature for %s, must be: func %s(%s *testing.%s)", pos, name, name, strings.ToLower(arg), arg) - } - return nil -} - -var testmainTmpl = template.Must(template.New("main").Parse(` -package main - -import ( -{{if not .TestMain}} - "os" -{{end}} - "testing" - "testing/internal/testdeps" - -{{if .ImportTest}} - {{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}} -{{end}} -{{if .ImportXtest}} - {{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}} -{{end}} -{{range $i, $p := .Cover}} - _cover{{$i}} {{$p.Package.ImportPath | printf "%q"}} -{{end}} -) - -var tests = []testing.InternalTest{ -{{range .Tests}} - {"{{.Name}}", {{.Package}}.{{.Name}}}, -{{end}} -} - -var benchmarks = []testing.InternalBenchmark{ -{{range .Benchmarks}} - {"{{.Name}}", {{.Package}}.{{.Name}}}, -{{end}} -} - -var examples = []testing.InternalExample{ -{{range .Examples}} - {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}}, -{{end}} -} - -func init() { - testdeps.ImportPath = {{.ImportPath | printf "%q"}} -} - -{{if .CoverEnabled}} - -// Only updated by init functions, so no need for atomicity. -var ( - coverCounters = make(map[string][]uint32) - coverBlocks = make(map[string][]testing.CoverBlock) -) - -func init() { - {{range $i, $p := .Cover}} - {{range $file, $cover := $p.Vars}} - coverRegisterFile({{printf "%q" $cover.File}}, _cover{{$i}}.{{$cover.Var}}.Count[:], _cover{{$i}}.{{$cover.Var}}.Pos[:], _cover{{$i}}.{{$cover.Var}}.NumStmt[:]) - {{end}} - {{end}} -} - -func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts []uint16) { - if 3*len(counter) != len(pos) || len(counter) != len(numStmts) { - panic("coverage: mismatched sizes") - } - if coverCounters[fileName] != nil { - // Already registered. - return - } - coverCounters[fileName] = counter - block := make([]testing.CoverBlock, len(counter)) - for i := range counter { - block[i] = testing.CoverBlock{ - Line0: pos[3*i+0], - Col0: uint16(pos[3*i+2]), - Line1: pos[3*i+1], - Col1: uint16(pos[3*i+2]>>16), - Stmts: numStmts[i], - } - } - coverBlocks[fileName] = block -} -{{end}} - -func main() { -{{if .CoverEnabled}} - testing.RegisterCover(testing.Cover{ - Mode: {{printf "%q" .CoverMode}}, - Counters: coverCounters, - Blocks: coverBlocks, - CoveredPackages: {{printf "%q" .Covered}}, - }) -{{end}} - m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, examples) -{{with .TestMain}} - {{.Package}}.{{.Name}}(m) -{{else}} - os.Exit(m.Run()) -{{end}} -} - -`)) diff --git a/libgo/go/cmd/go/internal/test/testflag.go b/libgo/go/cmd/go/internal/test/testflag.go index 8a686b71255..73f8c69d9e1 100644 --- a/libgo/go/cmd/go/internal/test/testflag.go +++ b/libgo/go/cmd/go/internal/test/testflag.go @@ -63,6 +63,7 @@ var testFlagDefn = []*cmdflag.Defn{ // add build flags to testFlagDefn func init() { + cmdflag.AddKnownFlags("test", testFlagDefn) var cmd base.Command work.AddBuildFlags(&cmd) cmd.Flag.VisitAll(func(f *flag.Flag) { @@ -87,6 +88,7 @@ func init() { // go test fmt -custom-flag-for-fmt-test // go test -x math func testFlags(args []string) (packageNames, passToTest []string) { + args = str.StringList(cmdflag.FindGOFLAGS(testFlagDefn), args) inPkg := false var explicitArgs []string for i := 0; i < len(args); i++ { diff --git a/libgo/go/cmd/go/internal/tool/tool.go b/libgo/go/cmd/go/internal/tool/tool.go index 4c7d0897e05..edcf93513d8 100644 --- a/libgo/go/cmd/go/internal/tool/tool.go +++ b/libgo/go/cmd/go/internal/tool/tool.go @@ -18,7 +18,7 @@ import ( var CmdTool = &base.Command{ Run: runTool, - UsageLine: "tool [-n] command [args...]", + UsageLine: "go tool [-n] command [args...]", Short: "run specified go tool", Long: ` Tool runs the go tool command identified by the arguments. diff --git a/libgo/go/cmd/go/internal/txtar/archive.go b/libgo/go/cmd/go/internal/txtar/archive.go new file mode 100644 index 00000000000..c384f33bdf8 --- /dev/null +++ b/libgo/go/cmd/go/internal/txtar/archive.go @@ -0,0 +1,140 @@ +// 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 txtar implements a trivial text-based file archive format. +// +// The goals for the format are: +// +// - be trivial enough to create and edit by hand. +// - be able to store trees of text files describing go command test cases. +// - diff nicely in git history and code reviews. +// +// Non-goals include being a completely general archive format, +// storing binary data, storing file modes, storing special files like +// symbolic links, and so on. +// +// Txtar format +// +// A txtar archive is zero or more comment lines and then a sequence of file entries. +// Each file entry begins with a file marker line of the form "-- FILENAME --" +// and is followed by zero or more file content lines making up the file data. +// The comment or file content ends at the next file marker line. +// The file marker line must begin with the three-byte sequence "-- " +// and end with the three-byte sequence " --", but the enclosed +// file name can be surrounding by additional white space, +// all of which is stripped. +// +// If the txtar file is missing a trailing newline on the final line, +// parsers should consider a final newline to be present anyway. +// +// There are no possible syntax errors in a txtar archive. +package txtar + +import ( + "bytes" + "fmt" + "io/ioutil" + "strings" +) + +// An Archive is a collection of files. +type Archive struct { + Comment []byte + Files []File +} + +// A File is a single file in an archive. +type File struct { + Name string // name of file ("foo/bar.txt") + Data []byte // text content of file +} + +// Format returns the serialized form of an Archive. +// It is assumed that the Archive data structure is well-formed: +// a.Comment and all a.File[i].Data contain no file marker lines, +// and all a.File[i].Name is non-empty. +func Format(a *Archive) []byte { + var buf bytes.Buffer + buf.Write(fixNL(a.Comment)) + for _, f := range a.Files { + fmt.Fprintf(&buf, "-- %s --\n", f.Name) + buf.Write(fixNL(f.Data)) + } + return buf.Bytes() +} + +// ParseFile parses the named file as an archive. +func ParseFile(file string) (*Archive, error) { + data, err := ioutil.ReadFile(file) + if err != nil { + return nil, err + } + return Parse(data), nil +} + +// Parse parses the serialized form of an Archive. +// The returned Archive holds slices of data. +func Parse(data []byte) *Archive { + a := new(Archive) + var name string + a.Comment, name, data = findFileMarker(data) + for name != "" { + f := File{name, nil} + f.Data, name, data = findFileMarker(data) + a.Files = append(a.Files, f) + } + return a +} + +var ( + newlineMarker = []byte("\n-- ") + marker = []byte("-- ") + markerEnd = []byte(" --") +) + +// findFileMarker finds the next file marker in data, +// extracts the file name, and returns the data before the marker, +// the file name, and the data after the marker. +// If there is no next marker, findFileMarker returns before = fixNL(data), name = "", after = nil. +func findFileMarker(data []byte) (before []byte, name string, after []byte) { + var i int + for { + if name, after = isMarker(data[i:]); name != "" { + return data[:i], name, after + } + j := bytes.Index(data[i:], newlineMarker) + if j < 0 { + return fixNL(data), "", nil + } + i += j + 1 // positioned at start of new possible marker + } +} + +// isMarker checks whether data begins with a file marker line. +// If so, it returns the name from the line and the data after the line. +// Otherwise it returns name == "" with an unspecified after. +func isMarker(data []byte) (name string, after []byte) { + if !bytes.HasPrefix(data, marker) { + return "", nil + } + if i := bytes.IndexByte(data, '\n'); i >= 0 { + data, after = data[:i], data[i+1:] + } + if !bytes.HasSuffix(data, markerEnd) { + return "", nil + } + return strings.TrimSpace(string(data[len(marker) : len(data)-len(markerEnd)])), after +} + +// If data is empty or ends in \n, fixNL returns data. +// Otherwise fixNL returns a new slice consisting of data with a final \n added. +func fixNL(data []byte) []byte { + if len(data) == 0 || data[len(data)-1] == '\n' { + return data + } + d := make([]byte, len(data)+1) + copy(d, data) + d[len(data)] = '\n' + return d +} diff --git a/libgo/go/cmd/go/internal/txtar/archive_test.go b/libgo/go/cmd/go/internal/txtar/archive_test.go new file mode 100644 index 00000000000..3f734f67625 --- /dev/null +++ b/libgo/go/cmd/go/internal/txtar/archive_test.go @@ -0,0 +1,67 @@ +// 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 txtar + +import ( + "bytes" + "fmt" + "reflect" + "testing" +) + +var tests = []struct { + name string + text string + parsed *Archive +}{ + { + name: "basic", + text: `comment1 +comment2 +-- file1 -- +File 1 text. +-- foo --- +More file 1 text. +-- file 2 -- +File 2 text. +-- empty -- +-- noNL -- +hello world`, + parsed: &Archive{ + Comment: []byte("comment1\ncomment2\n"), + Files: []File{ + {"file1", []byte("File 1 text.\n-- foo ---\nMore file 1 text.\n")}, + {"file 2", []byte("File 2 text.\n")}, + {"empty", []byte{}}, + {"noNL", []byte("hello world\n")}, + }, + }, + }, +} + +func Test(t *testing.T) { + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + a := Parse([]byte(tt.text)) + if !reflect.DeepEqual(a, tt.parsed) { + t.Fatalf("Parse: wrong output:\nhave:\n%s\nwant:\n%s", shortArchive(a), shortArchive(tt.parsed)) + } + text := Format(a) + a = Parse(text) + if !reflect.DeepEqual(a, tt.parsed) { + t.Fatalf("Parse after Format: wrong output:\nhave:\n%s\nwant:\n%s", shortArchive(a), shortArchive(tt.parsed)) + } + }) + } +} + +func shortArchive(a *Archive) string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "comment: %q\n", a.Comment) + for _, f := range a.Files { + fmt.Fprintf(&buf, "file %q: %q\n", f.Name, f.Data) + } + return buf.String() +} diff --git a/libgo/go/cmd/go/internal/version/version.go b/libgo/go/cmd/go/internal/version/version.go index c3f7d73ff1d..9344a28dc36 100644 --- a/libgo/go/cmd/go/internal/version/version.go +++ b/libgo/go/cmd/go/internal/version/version.go @@ -14,7 +14,7 @@ import ( var CmdVersion = &base.Command{ Run: runVersion, - UsageLine: "version", + UsageLine: "go version", Short: "print Go version", Long: `Version prints the Go version, as reported by runtime.Version.`, } diff --git a/libgo/go/cmd/go/internal/vet/vet.go b/libgo/go/cmd/go/internal/vet/vet.go index a737ebd669f..ea85fb8d5c9 100644 --- a/libgo/go/cmd/go/internal/vet/vet.go +++ b/libgo/go/cmd/go/internal/vet/vet.go @@ -8,6 +8,7 @@ package vet import ( "cmd/go/internal/base" "cmd/go/internal/load" + "cmd/go/internal/modload" "cmd/go/internal/work" "path/filepath" ) @@ -15,7 +16,7 @@ import ( var CmdVet = &base.Command{ Run: runVet, CustomFlags: true, - UsageLine: "vet [-n] [-x] [build flags] [vet flags] [packages]", + UsageLine: "go vet [-n] [-x] [build flags] [vet flags] [packages]", Short: "report likely mistakes in packages", Long: ` Vet runs the Go vet command on the packages named by the import paths. @@ -35,6 +36,8 @@ See also: go fmt, go fix. } func runVet(cmd *base.Command, args []string) { + modload.LoadTests = true + vetFlags, pkgArgs := vetFlags(args) work.BuildInit() @@ -57,7 +60,7 @@ func runVet(cmd *base.Command, args []string) { root := &work.Action{Mode: "go vet"} for _, p := range pkgs { - ptest, pxtest, err := load.GetTestPackagesFor(p, false) + _, ptest, pxtest, err := load.GetTestPackagesFor(p, nil) if err != nil { base.Errorf("%v", err) continue diff --git a/libgo/go/cmd/go/internal/vet/vetflag.go b/libgo/go/cmd/go/internal/vet/vetflag.go index 03770ea920e..50eac425ec3 100644 --- a/libgo/go/cmd/go/internal/vet/vetflag.go +++ b/libgo/go/cmd/go/internal/vet/vetflag.go @@ -12,6 +12,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cmdflag" + "cmd/go/internal/str" "cmd/go/internal/work" ) @@ -26,39 +27,40 @@ var vetFlagDefn = []*cmdflag.Defn{ // to vet. We handle them in vetFlags. // local. - {Name: "all", BoolVar: new(bool)}, - {Name: "asmdecl", BoolVar: new(bool)}, - {Name: "assign", BoolVar: new(bool)}, - {Name: "atomic", BoolVar: new(bool)}, - {Name: "bool", BoolVar: new(bool)}, - {Name: "buildtags", BoolVar: new(bool)}, - {Name: "cgocall", BoolVar: new(bool)}, - {Name: "composites", BoolVar: new(bool)}, - {Name: "copylocks", BoolVar: new(bool)}, - {Name: "httpresponse", BoolVar: new(bool)}, - {Name: "lostcancel", BoolVar: new(bool)}, - {Name: "methods", BoolVar: new(bool)}, - {Name: "nilfunc", BoolVar: new(bool)}, - {Name: "printf", BoolVar: new(bool)}, - {Name: "printfuncs"}, - {Name: "rangeloops", BoolVar: new(bool)}, - {Name: "shadow", BoolVar: new(bool)}, - {Name: "shadowstrict", BoolVar: new(bool)}, - {Name: "shift", BoolVar: new(bool)}, - {Name: "source", BoolVar: new(bool)}, - {Name: "structtags", BoolVar: new(bool)}, - {Name: "tests", BoolVar: new(bool)}, - {Name: "unreachable", BoolVar: new(bool)}, - {Name: "unsafeptr", BoolVar: new(bool)}, - {Name: "unusedfuncs"}, - {Name: "unusedresult", BoolVar: new(bool)}, - {Name: "unusedstringmethods"}, + {Name: "all", BoolVar: new(bool), PassToTest: true}, + {Name: "asmdecl", BoolVar: new(bool), PassToTest: true}, + {Name: "assign", BoolVar: new(bool), PassToTest: true}, + {Name: "atomic", BoolVar: new(bool), PassToTest: true}, + {Name: "bool", BoolVar: new(bool), PassToTest: true}, + {Name: "buildtags", BoolVar: new(bool), PassToTest: true}, + {Name: "cgocall", BoolVar: new(bool), PassToTest: true}, + {Name: "composites", BoolVar: new(bool), PassToTest: true}, + {Name: "copylocks", BoolVar: new(bool), PassToTest: true}, + {Name: "httpresponse", BoolVar: new(bool), PassToTest: true}, + {Name: "lostcancel", BoolVar: new(bool), PassToTest: true}, + {Name: "methods", BoolVar: new(bool), PassToTest: true}, + {Name: "nilfunc", BoolVar: new(bool), PassToTest: true}, + {Name: "printf", BoolVar: new(bool), PassToTest: true}, + {Name: "printfuncs", PassToTest: true}, + {Name: "rangeloops", BoolVar: new(bool), PassToTest: true}, + {Name: "shadow", BoolVar: new(bool), PassToTest: true}, + {Name: "shadowstrict", BoolVar: new(bool), PassToTest: true}, + {Name: "shift", BoolVar: new(bool), PassToTest: true}, + {Name: "source", BoolVar: new(bool), PassToTest: true}, + {Name: "structtags", BoolVar: new(bool), PassToTest: true}, + {Name: "tests", BoolVar: new(bool), PassToTest: true}, + {Name: "unreachable", BoolVar: new(bool), PassToTest: true}, + {Name: "unsafeptr", BoolVar: new(bool), PassToTest: true}, + {Name: "unusedfuncs", PassToTest: true}, + {Name: "unusedresult", BoolVar: new(bool), PassToTest: true}, + {Name: "unusedstringmethods", PassToTest: true}, } var vetTool string // add build flags to vetFlagDefn. func init() { + cmdflag.AddKnownFlags("vet", vetFlagDefn) var cmd base.Command work.AddBuildFlags(&cmd) cmd.Flag.StringVar(&vetTool, "vettool", "", "path to vet tool binary") // for cmd/vet tests; undocumented for now @@ -73,6 +75,7 @@ func init() { // vetFlags processes the command line, splitting it at the first non-flag // into the list of flags and list of packages. func vetFlags(args []string) (passToVet, packageNames []string) { + args = str.StringList(cmdflag.FindGOFLAGS(vetFlagDefn), args) for i := 0; i < len(args); i++ { if !strings.HasPrefix(args[i], "-") { return args[:i], args[i:] @@ -88,9 +91,17 @@ func vetFlags(args []string) (passToVet, packageNames []string) { if err := f.Value.Set(value); err != nil { base.Fatalf("invalid flag argument for -%s: %v", f.Name, err) } - switch f.Name { - // Flags known to the build but not to vet, so must be dropped. - case "x", "n", "vettool", "compiler": + keep := f.PassToTest + if !keep { + // A build flag, probably one we don't want to pass to vet. + // Can whitelist. + switch f.Name { + case "tags", "v": + keep = true + } + } + if !keep { + // Flags known to the build but not to vet, so must be dropped. if extraWord { args = append(args[:i], args[i+2:]...) extraWord = false diff --git a/libgo/go/cmd/go/internal/web2/web.go b/libgo/go/cmd/go/internal/web2/web.go new file mode 100644 index 00000000000..f3900379e17 --- /dev/null +++ b/libgo/go/cmd/go/internal/web2/web.go @@ -0,0 +1,297 @@ +// 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 web2 + +import ( + "bytes" + "cmd/go/internal/base" + "encoding/json" + "flag" + "fmt" + "io" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "runtime" + "runtime/debug" + "strings" + "sync" +) + +var TraceGET = false +var webstack = false + +func init() { + flag.BoolVar(&TraceGET, "webtrace", TraceGET, "trace GET requests") + flag.BoolVar(&webstack, "webstack", webstack, "print stack for GET requests") +} + +type netrcLine struct { + machine string + login string + password string +} + +var netrcOnce sync.Once +var netrc []netrcLine + +func parseNetrc(data string) []netrcLine { + var nrc []netrcLine + var l netrcLine + for _, line := range strings.Split(data, "\n") { + f := strings.Fields(line) + for i := 0; i < len(f)-1; i += 2 { + switch f[i] { + case "machine": + l.machine = f[i+1] + case "login": + l.login = f[i+1] + case "password": + l.password = f[i+1] + } + } + if l.machine != "" && l.login != "" && l.password != "" { + nrc = append(nrc, l) + l = netrcLine{} + } + } + return nrc +} + +func havePassword(machine string) bool { + netrcOnce.Do(readNetrc) + for _, line := range netrc { + if line.machine == machine { + return true + } + } + return false +} + +func netrcPath() string { + switch runtime.GOOS { + case "windows": + return filepath.Join(os.Getenv("USERPROFILE"), "_netrc") + case "plan9": + return filepath.Join(os.Getenv("home"), ".netrc") + default: + return filepath.Join(os.Getenv("HOME"), ".netrc") + } +} + +func readNetrc() { + data, err := ioutil.ReadFile(netrcPath()) + if err != nil { + return + } + netrc = parseNetrc(string(data)) +} + +type getState struct { + req *http.Request + resp *http.Response + body io.ReadCloser + non200ok bool +} + +type Option interface { + option(*getState) error +} + +func Non200OK() Option { + return optionFunc(func(g *getState) error { + g.non200ok = true + return nil + }) +} + +type optionFunc func(*getState) error + +func (f optionFunc) option(g *getState) error { + return f(g) +} + +func DecodeJSON(dst interface{}) Option { + return optionFunc(func(g *getState) error { + if g.resp != nil { + return json.NewDecoder(g.body).Decode(dst) + } + return nil + }) +} + +func ReadAllBody(body *[]byte) Option { + return optionFunc(func(g *getState) error { + if g.resp != nil { + var err error + *body, err = ioutil.ReadAll(g.body) + return err + } + return nil + }) +} + +func Body(body *io.ReadCloser) Option { + return optionFunc(func(g *getState) error { + if g.resp != nil { + *body = g.body + g.body = nil + } + return nil + }) +} + +func Header(hdr *http.Header) Option { + return optionFunc(func(g *getState) error { + if g.resp != nil { + *hdr = CopyHeader(g.resp.Header) + } + return nil + }) +} + +func CopyHeader(hdr http.Header) http.Header { + if hdr == nil { + return nil + } + h2 := make(http.Header) + for k, v := range hdr { + v2 := make([]string, len(v)) + copy(v2, v) + h2[k] = v2 + } + return h2 +} + +var cache struct { + mu sync.Mutex + byURL map[string]*cacheEntry +} + +type cacheEntry struct { + mu sync.Mutex + resp *http.Response + body []byte +} + +var httpDo = http.DefaultClient.Do + +func SetHTTPDoForTesting(do func(*http.Request) (*http.Response, error)) { + if do == nil { + do = http.DefaultClient.Do + } + httpDo = do +} + +func Get(url string, options ...Option) error { + if TraceGET || webstack { + println("GET", url) + if webstack { + println(string(debug.Stack())) + } + } + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return err + } + + netrcOnce.Do(readNetrc) + for _, l := range netrc { + if l.machine == req.URL.Host { + req.SetBasicAuth(l.login, l.password) + break + } + } + + g := &getState{req: req} + for _, o := range options { + if err := o.option(g); err != nil { + return err + } + } + + cache.mu.Lock() + e := cache.byURL[url] + if e == nil { + e = new(cacheEntry) + if !strings.HasPrefix(url, "file:") { + if cache.byURL == nil { + cache.byURL = make(map[string]*cacheEntry) + } + cache.byURL[url] = e + } + } + cache.mu.Unlock() + + e.mu.Lock() + if strings.HasPrefix(url, "file:") { + body, err := ioutil.ReadFile(req.URL.Path) + if err != nil { + e.mu.Unlock() + return err + } + e.body = body + e.resp = &http.Response{ + StatusCode: 200, + } + } else if e.resp == nil { + resp, err := httpDo(req) + if err != nil { + e.mu.Unlock() + return err + } + e.resp = resp + // TODO: Spool to temp file. + body, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + resp.Body = nil + if err != nil { + e.mu.Unlock() + return err + } + e.body = body + } + g.resp = e.resp + g.body = ioutil.NopCloser(bytes.NewReader(e.body)) + e.mu.Unlock() + + defer func() { + if g.body != nil { + g.body.Close() + } + }() + + if g.resp.StatusCode == 403 && req.URL.Host == "api.github.com" && !havePassword("api.github.com") { + base.Errorf("%s", githubMessage) + } + if !g.non200ok && g.resp.StatusCode != 200 { + return fmt.Errorf("unexpected status (%s): %v", url, g.resp.Status) + } + + for _, o := range options { + if err := o.option(g); err != nil { + return err + } + } + return err +} + +var githubMessage = `go: 403 response from api.github.com + +GitHub applies fairly small rate limits to unauthenticated users, and +you appear to be hitting them. To authenticate, please visit +https://github.com/settings/tokens and click "Generate New Token" to +create a Personal Access Token. The token only needs "public_repo" +scope, but you can add "repo" if you want to access private +repositories too. + +Add the token to your $HOME/.netrc (%USERPROFILE%\_netrc on Windows): + + machine api.github.com login YOU password TOKEN + +Sorry for the interruption. +` diff --git a/libgo/go/cmd/go/internal/web2/web_test.go b/libgo/go/cmd/go/internal/web2/web_test.go new file mode 100644 index 00000000000..c6f6b1eff4d --- /dev/null +++ b/libgo/go/cmd/go/internal/web2/web_test.go @@ -0,0 +1,35 @@ +// 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 web2 + +import ( + "reflect" + "testing" +) + +var testNetrc = ` +machine api.github.com + login user + password pwd + +machine incomlete.host + login justlogin + +machine test.host +login user2 +password pwd2 +` + +func TestReadNetrc(t *testing.T) { + lines := parseNetrc(testNetrc) + want := []netrcLine{ + {"api.github.com", "user", "pwd"}, + {"test.host", "user2", "pwd2"}, + } + + if !reflect.DeepEqual(lines, want) { + t.Errorf("parseNetrc:\nhave %q\nwant %q", lines, want) + } +} diff --git a/libgo/go/cmd/go/internal/webtest/test.go b/libgo/go/cmd/go/internal/webtest/test.go new file mode 100644 index 00000000000..94b20a33ffc --- /dev/null +++ b/libgo/go/cmd/go/internal/webtest/test.go @@ -0,0 +1,314 @@ +// 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 webtest + +import ( + "bufio" + "bytes" + "encoding/hex" + "flag" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "os" + "sort" + "strconv" + "strings" + "sync" + "unicode/utf8" + + web "cmd/go/internal/web2" +) + +var mode = flag.String("webtest", "replay", "set webtest `mode` - record, replay, bypass") + +func Hook() { + if *mode == "bypass" { + return + } + web.SetHTTPDoForTesting(Do) +} + +func Unhook() { + web.SetHTTPDoForTesting(nil) +} + +func Print() { + web.SetHTTPDoForTesting(DoPrint) +} + +var responses struct { + mu sync.Mutex + byURL map[string]*respEntry +} + +type respEntry struct { + status string + code int + hdr http.Header + body []byte +} + +func Serve(url string, status string, hdr http.Header, body []byte) { + if status == "" { + status = "200 OK" + } + code, err := strconv.Atoi(strings.Fields(status)[0]) + if err != nil { + panic("bad Serve status - " + status + " - " + err.Error()) + } + + responses.mu.Lock() + defer responses.mu.Unlock() + + if responses.byURL == nil { + responses.byURL = make(map[string]*respEntry) + } + responses.byURL[url] = &respEntry{status: status, code: code, hdr: web.CopyHeader(hdr), body: body} +} + +func Do(req *http.Request) (*http.Response, error) { + if req.Method != "GET" { + return nil, fmt.Errorf("bad method - must be GET") + } + + responses.mu.Lock() + e := responses.byURL[req.URL.String()] + responses.mu.Unlock() + + if e == nil { + if *mode == "record" { + loaded.mu.Lock() + if len(loaded.did) != 1 { + loaded.mu.Unlock() + return nil, fmt.Errorf("cannot use -webtest=record with multiple loaded response files") + } + var file string + for file = range loaded.did { + break + } + loaded.mu.Unlock() + return doSave(file, req) + } + e = &respEntry{code: 599, status: "599 unexpected request (no canned response)"} + } + resp := &http.Response{ + Status: e.status, + StatusCode: e.code, + Header: web.CopyHeader(e.hdr), + Body: ioutil.NopCloser(bytes.NewReader(e.body)), + } + return resp, nil +} + +func DoPrint(req *http.Request) (*http.Response, error) { + return doSave("", req) +} + +func doSave(file string, req *http.Request) (*http.Response, error) { + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + data, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + return nil, err + } + resp.Body = ioutil.NopCloser(bytes.NewReader(data)) + + var f *os.File + if file == "" { + f = os.Stderr + } else { + f, err = os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + log.Fatal(err) + } + defer f.Close() + } + + fmt.Fprintf(f, "GET %s\n", req.URL.String()) + fmt.Fprintf(f, "%s\n", resp.Status) + var keys []string + for k := range resp.Header { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + if k == "Set-Cookie" { + continue + } + for _, v := range resp.Header[k] { + fmt.Fprintf(f, "%s: %s\n", k, v) + } + } + fmt.Fprintf(f, "\n") + if utf8.Valid(data) && !bytes.Contains(data, []byte("\nGET")) && !isHexDump(data) { + fmt.Fprintf(f, "%s\n\n", data) + } else { + fmt.Fprintf(f, "%s\n", hex.Dump(data)) + } + return resp, err +} + +var loaded struct { + mu sync.Mutex + did map[string]bool +} + +func LoadOnce(file string) { + loaded.mu.Lock() + if loaded.did[file] { + loaded.mu.Unlock() + return + } + if loaded.did == nil { + loaded.did = make(map[string]bool) + } + loaded.did[file] = true + loaded.mu.Unlock() + + f, err := os.Open(file) + if err != nil { + log.Fatal(err) + } + defer f.Close() + + b := bufio.NewReader(f) + var ungetLine string + nextLine := func() string { + if ungetLine != "" { + l := ungetLine + ungetLine = "" + return l + } + line, err := b.ReadString('\n') + if err != nil { + if err == io.EOF { + return "" + } + log.Fatalf("%s: unexpected read error: %v", file, err) + } + return line + } + + for { + line := nextLine() + if line == "" { // EOF + break + } + line = strings.TrimSpace(line) + if strings.HasPrefix(line, "#") || line == "" { + continue + } + if !strings.HasPrefix(line, "GET ") { + log.Fatalf("%s: malformed GET line: %s", file, line) + } + url := line[len("GET "):] + status := nextLine() + if _, err := strconv.Atoi(strings.Fields(status)[0]); err != nil { + log.Fatalf("%s: malformed status line (after GET %s): %s", file, url, status) + } + hdr := make(http.Header) + for { + kv := strings.TrimSpace(nextLine()) + if kv == "" { + break + } + i := strings.Index(kv, ":") + if i < 0 { + log.Fatalf("%s: malformed header line (after GET %s): %s", file, url, kv) + } + k, v := kv[:i], strings.TrimSpace(kv[i+1:]) + hdr[k] = append(hdr[k], v) + } + + var body []byte + Body: + for n := 0; ; n++ { + line := nextLine() + if n == 0 && isHexDump([]byte(line)) { + ungetLine = line + b, err := parseHexDump(nextLine) + if err != nil { + log.Fatalf("%s: malformed hex dump (after GET %s): %v", file, url, err) + } + body = b + break + } + if line == "" { // EOF + for i := 0; i < 2; i++ { + if len(body) > 0 && body[len(body)-1] == '\n' { + body = body[:len(body)-1] + } + } + break + } + body = append(body, line...) + for line == "\n" { + line = nextLine() + if strings.HasPrefix(line, "GET ") { + ungetLine = line + body = body[:len(body)-1] + if len(body) > 0 { + body = body[:len(body)-1] + } + break Body + } + body = append(body, line...) + } + } + + Serve(url, status, hdr, body) + } +} + +func isHexDump(data []byte) bool { + return bytes.HasPrefix(data, []byte("00000000 ")) || bytes.HasPrefix(data, []byte("0000000 ")) +} + +// parseHexDump parses the hex dump in text, which should be the +// output of "hexdump -C" or Plan 9's "xd -b" or Go's hex.Dump +// and returns the original data used to produce the dump. +// It is meant to enable storing golden binary files as text, so that +// changes to the golden files can be seen during code reviews. +func parseHexDump(nextLine func() string) ([]byte, error) { + var out []byte + for { + line := nextLine() + if line == "" || line == "\n" { + break + } + if i := strings.Index(line, "|"); i >= 0 { // remove text dump + line = line[:i] + } + f := strings.Fields(line) + if len(f) > 1+16 { + return nil, fmt.Errorf("parsing hex dump: too many fields on line %q", line) + } + if len(f) == 0 || len(f) == 1 && f[0] == "*" { // all zeros block omitted + continue + } + addr64, err := strconv.ParseUint(f[0], 16, 0) + if err != nil { + return nil, fmt.Errorf("parsing hex dump: invalid address %q", f[0]) + } + addr := int(addr64) + if len(out) < addr { + out = append(out, make([]byte, addr-len(out))...) + } + for _, x := range f[1:] { + val, err := strconv.ParseUint(x, 16, 8) + if err != nil { + return nil, fmt.Errorf("parsing hexdump: invalid hex byte %q", x) + } + out = append(out, byte(val)) + } + } + return out, nil +} diff --git a/libgo/go/cmd/go/internal/work/action.go b/libgo/go/cmd/go/internal/work/action.go index 803a6bd4611..82cf228fa44 100644 --- a/libgo/go/cmd/go/internal/work/action.go +++ b/libgo/go/cmd/go/internal/work/action.go @@ -37,7 +37,10 @@ type Builder struct { flagCache map[[2]string]bool // a cache of supported compiler flags Print func(args ...interface{}) (int, error) - ComputeStaleOnly bool // compute staleness for go list; no actual build + IsCmdList bool // running as part of go list; set p.Stale and additional fields below + NeedError bool // list needs p.Error + NeedExport bool // list needs p.Export + NeedCompiledGoFiles bool // list needs p.CompiledGoFIles objdirSeq int // counter for NewObjdir pkgSeq int @@ -80,9 +83,10 @@ type Action struct { actionID cache.ActionID // cache ID of action input buildID string // build ID of action output - needVet bool // Mode=="build": need to fill in vet config - vetCfg *vetConfig // vet config - output []byte // output redirect buffer (nil means use b.Print) + VetxOnly bool // Mode=="vet": only being called to supply info about dependencies + needVet bool // Mode=="build": need to fill in vet config + vetCfg *vetConfig // vet config + output []byte // output redirect buffer (nil means use b.Print) // Execution state. pending int // number of deps yet to complete @@ -139,6 +143,7 @@ type actionJSON struct { Priority int `json:",omitempty"` Failed bool `json:",omitempty"` Built string `json:",omitempty"` + VetxOnly bool `json:",omitempty"` } // cacheKey is the key for the action cache. @@ -178,6 +183,7 @@ func actionGraphJSON(a *Action) string { Failed: a.Failed, Priority: a.priority, Built: a.built, + VetxOnly: a.VetxOnly, } if a.Package != nil { // TODO(rsc): Make this a unique key for a.Package somehow. @@ -208,7 +214,6 @@ const ( ) func (b *Builder) Init() { - var err error b.Print = func(a ...interface{}) (int, error) { return fmt.Fprint(os.Stderr, a...) } @@ -220,10 +225,19 @@ func (b *Builder) Init() { if cfg.BuildN { b.WorkDir = "$WORK" } else { - b.WorkDir, err = ioutil.TempDir(os.Getenv("GOTMPDIR"), "go-build") + tmp, err := ioutil.TempDir(os.Getenv("GOTMPDIR"), "go-build") if err != nil { - base.Fatalf("%s", err) + base.Fatalf("go: creating work dir: %v", err) } + if !filepath.IsAbs(tmp) { + abs, err := filepath.Abs(tmp) + if err != nil { + os.RemoveAll(tmp) + base.Fatalf("go: creating work dir: %v", err) + } + tmp = abs + } + b.WorkDir = tmp if cfg.BuildX || cfg.BuildWork { fmt.Fprintf(os.Stderr, "WORK=%s\n", b.WorkDir) } @@ -322,8 +336,8 @@ func (b *Builder) AutoAction(mode, depMode BuildMode, p *load.Package) *Action { // depMode is the action (build or install) to use when building dependencies. // To turn package main into an executable, call b.Link instead. func (b *Builder) CompileAction(mode, depMode BuildMode, p *load.Package) *Action { - if mode != ModeBuild && p.Internal.Local && p.Target == "" { - // Imported via local path. No permanent target. + if mode != ModeBuild && (p.Internal.Local || p.Module != nil) && p.Target == "" { + // Imported via local path or using modules. No permanent target. mode = ModeBuild } if mode != ModeBuild && p.Name == "main" { @@ -340,8 +354,10 @@ func (b *Builder) CompileAction(mode, depMode BuildMode, p *load.Package) *Actio Objdir: b.NewObjdir(), } - for _, p1 := range p.Internal.Imports { - a.Deps = append(a.Deps, b.CompileAction(depMode, depMode, p1)) + if p.Error == nil || !p.Error.IsImportCycle { + for _, p1 := range p.Internal.Imports { + a.Deps = append(a.Deps, b.CompileAction(depMode, depMode, p1)) + } } if p.Standard { @@ -379,6 +395,12 @@ func (b *Builder) CompileAction(mode, depMode BuildMode, p *load.Package) *Actio // If the caller may be causing p to be installed, it is up to the caller // to make sure that the install depends on (runs after) vet. func (b *Builder) VetAction(mode, depMode BuildMode, p *load.Package) *Action { + a := b.vetAction(mode, depMode, p) + a.VetxOnly = false + return a +} + +func (b *Builder) vetAction(mode, depMode BuildMode, p *load.Package) *Action { // Construct vet action. a := b.cacheAction("vet", p, func() *Action { a1 := b.CompileAction(mode, depMode, p) @@ -390,19 +412,34 @@ func (b *Builder) VetAction(mode, depMode BuildMode, p *load.Package) *Action { stk.Pop() aFmt := b.CompileAction(ModeBuild, depMode, p1) + var deps []*Action + if a1.buggyInstall { + // (*Builder).vet expects deps[0] to be the package + // and deps[1] to be "fmt". If we see buggyInstall + // here then a1 is an install of a shared library, + // and the real package is a1.Deps[0]. + deps = []*Action{a1.Deps[0], aFmt, a1} + } else { + deps = []*Action{a1, aFmt} + } + for _, p1 := range load.PackageList(p.Internal.Imports) { + deps = append(deps, b.vetAction(mode, depMode, p1)) + } + a := &Action{ - Mode: "vet", - Package: p, - Deps: []*Action{a1, aFmt}, - Objdir: a1.Objdir, + Mode: "vet", + Package: p, + Deps: deps, + Objdir: a1.Objdir, + VetxOnly: true, + IgnoreFail: true, // it's OK if vet of dependencies "fails" (reports problems) } if a1.Func == nil { // Built-in packages like unsafe. return a } - a1.needVet = true + deps[0].needVet = true a.Func = (*Builder).vet - return a }) return a diff --git a/libgo/go/cmd/go/internal/work/build.go b/libgo/go/cmd/go/internal/work/build.go index 25dfe58d4bf..ed41ce5d073 100644 --- a/libgo/go/cmd/go/internal/work/build.go +++ b/libgo/go/cmd/go/internal/work/build.go @@ -18,10 +18,11 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/load" + "cmd/go/internal/search" ) var CmdBuild = &base.Command{ - UsageLine: "build [-o output] [-i] [build flags] [packages]", + UsageLine: "go build [-o output] [-i] [build flags] [packages]", Short: "compile packages and dependencies", Long: ` Build compiles the packages named by the import paths, @@ -65,7 +66,7 @@ and test commands: Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. -msan enable interoperation with memory sanitizer. - Supported only on linux/amd64, + Supported only on linux/amd64, linux/arm64 and only with Clang/LLVM as the host C compiler. -v print the names of packages as they are compiled. @@ -97,6 +98,9 @@ and test commands: -linkshared link against shared libraries previously created with -buildmode=shared. + -mod mode + module download mode to use: readonly, release, or vendor. + See 'go help modules' for more. -pkgdir dir install and load all packages from dir instead of the usual locations. For example, when building with a non-standard configuration, @@ -217,6 +221,7 @@ func AddBuildFlags(cmd *base.Command) { cmd.Flag.StringVar(&cfg.BuildBuildmode, "buildmode", "default", "") cmd.Flag.Var(&load.BuildGcflags, "gcflags", "") cmd.Flag.Var(&load.BuildGccgoflags, "gccgoflags", "") + cmd.Flag.StringVar(&cfg.BuildMod, "mod", "", "") cmd.Flag.StringVar(&cfg.BuildContext.InstallSuffix, "installsuffix", "", "") cmd.Flag.Var(&load.BuildLdflags, "ldflags", "") cmd.Flag.BoolVar(&cfg.BuildLinkshared, "linkshared", false, "") @@ -284,11 +289,6 @@ func runBuild(cmd *base.Command, args []string) { cfg.BuildO += cfg.ExeSuffix } - // Special case -o /dev/null by not writing at all. - if cfg.BuildO == os.DevNull { - cfg.BuildO = "" - } - // sanity check some often mis-used options switch cfg.BuildContext.Compiler { case "gccgo": @@ -309,7 +309,12 @@ func runBuild(cmd *base.Command, args []string) { depMode = ModeInstall } - pkgs = pkgsFilter(load.Packages(args)) + pkgs = omitTestOnly(pkgsFilter(load.Packages(args))) + + // Special case -o /dev/null by not writing at all. + if cfg.BuildO == os.DevNull { + cfg.BuildO = "" + } if cfg.BuildO != "" { if len(pkgs) > 1 { @@ -337,7 +342,7 @@ func runBuild(cmd *base.Command, args []string) { } var CmdInstall = &base.Command{ - UsageLine: "install [-i] [build flags] [packages]", + UsageLine: "go install [-i] [build flags] [packages]", Short: "compile and install packages and dependencies", Long: ` Install compiles and installs the packages named by the import paths. @@ -376,7 +381,7 @@ func libname(args []string, pkgs []*load.Package) (string, error) { } var haveNonMeta bool for _, arg := range args { - if load.IsMetaPackage(arg) { + if search.IsMetaPackage(arg) { appendName(arg) } else { haveNonMeta = true @@ -409,19 +414,44 @@ func libname(args []string, pkgs []*load.Package) (string, error) { func runInstall(cmd *base.Command, args []string) { BuildInit() - InstallPackages(args, false) + InstallPackages(args, load.PackagesForBuild(args)) } -func InstallPackages(args []string, forGet bool) { +// omitTestOnly returns pkgs with test-only packages removed. +func omitTestOnly(pkgs []*load.Package) []*load.Package { + var list []*load.Package + for _, p := range pkgs { + if len(p.GoFiles)+len(p.CgoFiles) == 0 && !p.Internal.CmdlinePkgLiteral { + // Package has no source files, + // perhaps due to build tags or perhaps due to only having *_test.go files. + // Also, it is only being processed as the result of a wildcard match + // like ./..., not because it was listed as a literal path on the command line. + // Ignore it. + continue + } + list = append(list, p) + } + return list +} + +func InstallPackages(patterns []string, pkgs []*load.Package) { if cfg.GOBIN != "" && !filepath.IsAbs(cfg.GOBIN) { base.Fatalf("cannot install, GOBIN must be an absolute path") } - pkgs := pkgsFilter(load.PackagesForBuild(args)) - + pkgs = omitTestOnly(pkgsFilter(pkgs)) for _, p := range pkgs { - if p.Target == "" && (!p.Standard || p.ImportPath != "unsafe") { + if p.Target == "" { switch { + case p.Standard && p.ImportPath == "unsafe": + // unsafe is a built-in package, has no target + case p.Name != "main" && p.Internal.Local && p.ConflictDir == "": + // Non-executables outside GOPATH need not have a target: + // we can use the cache to hold the built package archive for use in future builds. + // The ones inside GOPATH should have a target (in GOPATH/pkg) + // or else something is wrong and worth reporting (like a ConflictDir). + case p.Name != "main" && p.Module != nil: + // Non-executables have no target (except the cache) when building with modules. case p.Internal.GobinSubdir: base.Errorf("go %s: cannot install cross-compiled binaries when GOBIN is set", cfg.CmdName) case p.Internal.CmdlineFiles: @@ -445,11 +475,6 @@ func InstallPackages(args []string, forGet bool) { a := &Action{Mode: "go install"} var tools []*Action for _, p := range pkgs { - // During 'go get', don't attempt (and fail) to install packages with only tests. - // TODO(rsc): It's not clear why 'go get' should be different from 'go install' here. See #20760. - if forGet && len(p.GoFiles)+len(p.CgoFiles) == 0 && len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 { - continue - } // If p is a tool, delay the installation until the end of the build. // This avoids installing assemblers/compilers that are being executed // by other steps in the build. @@ -475,7 +500,7 @@ func InstallPackages(args []string, forGet bool) { // tools above did not apply, and a is just a simple Action // with a list of Deps, one per package named in pkgs, // the same as in runBuild. - a = b.buildmodeShared(ModeInstall, ModeInstall, args, pkgs, a) + a = b.buildmodeShared(ModeInstall, ModeInstall, patterns, pkgs, a) } b.Do(a) @@ -490,7 +515,7 @@ func InstallPackages(args []string, forGet bool) { // One way to view this behavior is that it is as if 'go install' first // runs 'go build' and the moves the generated file to the install dir. // See issue 9645. - if len(args) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" { + if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" { // Compute file 'go build' would have created. // If it exists and is an executable file, remove it. _, targ := filepath.Split(pkgs[0].ImportPath) diff --git a/libgo/go/cmd/go/internal/work/build_test.go b/libgo/go/cmd/go/internal/work/build_test.go index 3f5ba37c641..010e17ee480 100644 --- a/libgo/go/cmd/go/internal/work/build_test.go +++ b/libgo/go/cmd/go/internal/work/build_test.go @@ -42,15 +42,60 @@ func TestSplitPkgConfigOutput(t *testing.T) { }{ {[]byte(`-r:foo -L/usr/white\ space/lib -lfoo\ bar -lbar\ baz`), []string{"-r:foo", "-L/usr/white space/lib", "-lfoo bar", "-lbar baz"}}, {[]byte(`-lextra\ fun\ arg\\`), []string{`-lextra fun arg\`}}, - {[]byte(`broken flag\`), []string{"broken", "flag"}}, {[]byte("\textra whitespace\r\n"), []string{"extra", "whitespace"}}, {[]byte(" \r\n "), nil}, + {[]byte(`"-r:foo" "-L/usr/white space/lib" "-lfoo bar" "-lbar baz"`), []string{"-r:foo", "-L/usr/white space/lib", "-lfoo bar", "-lbar baz"}}, + {[]byte(`"-lextra fun arg\\"`), []string{`-lextra fun arg\`}}, + {[]byte(`" \r\n\ "`), []string{` \r\n\ `}}, + {[]byte(`""`), nil}, + {[]byte(``), nil}, + {[]byte(`"\\"`), []string{`\`}}, + {[]byte(`"\x"`), []string{`\x`}}, + {[]byte(`"\\x"`), []string{`\x`}}, + {[]byte(`'\\'`), []string{`\`}}, + {[]byte(`'\x'`), []string{`\x`}}, + {[]byte(`"\\x"`), []string{`\x`}}, + {[]byte(`-fPIC -I/test/include/foo -DQUOTED='"/test/share/doc"'`), []string{"-fPIC", "-I/test/include/foo", `-DQUOTED="/test/share/doc"`}}, + {[]byte(`-fPIC -I/test/include/foo -DQUOTED="/test/share/doc"`), []string{"-fPIC", "-I/test/include/foo", "-DQUOTED=/test/share/doc"}}, + {[]byte(`-fPIC -I/test/include/foo -DQUOTED=\"/test/share/doc\"`), []string{"-fPIC", "-I/test/include/foo", `-DQUOTED="/test/share/doc"`}}, + {[]byte(`-fPIC -I/test/include/foo -DQUOTED='/test/share/doc'`), []string{"-fPIC", "-I/test/include/foo", "-DQUOTED=/test/share/doc"}}, + {[]byte(`-DQUOTED='/te\st/share/d\oc'`), []string{`-DQUOTED=/te\st/share/d\oc`}}, + {[]byte(`-Dhello=10 -Dworld=+32 -DDEFINED_FROM_PKG_CONFIG=hello\ world`), []string{"-Dhello=10", "-Dworld=+32", "-DDEFINED_FROM_PKG_CONFIG=hello world"}}, + {[]byte(`"broken\"" \\\a "a"`), []string{"broken\"", "\\a", "a"}}, } { - got := splitPkgConfigOutput(test.in) + got, err := splitPkgConfigOutput(test.in) + if err != nil { + t.Errorf("splitPkgConfigOutput on %v failed with error %v", test.in, err) + continue + } if !reflect.DeepEqual(got, test.want) { t.Errorf("splitPkgConfigOutput(%v) = %v; want %v", test.in, got, test.want) } } + + for _, test := range []struct { + in []byte + want []string + }{ + // broken quotation + {[]byte(`" \r\n `), nil}, + {[]byte(`"-r:foo" "-L/usr/white space/lib "-lfoo bar" "-lbar baz"`), nil}, + {[]byte(`"-lextra fun arg\\`), nil}, + // broken char escaping + {[]byte(`broken flag\`), nil}, + {[]byte(`extra broken flag \`), nil}, + {[]byte(`\`), nil}, + {[]byte(`"broken\"" "extra" \`), nil}, + } { + got, err := splitPkgConfigOutput(test.in) + if err == nil { + t.Errorf("splitPkgConfigOutput(%v) = %v; haven't failed with error as expected.", test.in, got) + } + if !reflect.DeepEqual(got, test.want) { + t.Errorf("splitPkgConfigOutput(%v) = %v; want %v", test.in, got, test.want) + } + } + } func TestSharedLibName(t *testing.T) { @@ -220,7 +265,7 @@ func TestRespectSetgidDir(t *testing.T) { defer pkgfile.Close() dirGIDFile := filepath.Join(setgiddir, "setgid") - if err := b.moveOrCopyFile(nil, dirGIDFile, pkgfile.Name(), 0666, true); err != nil { + if err := b.moveOrCopyFile(dirGIDFile, pkgfile.Name(), 0666, true); err != nil { t.Fatalf("moveOrCopyFile: %v", err) } diff --git a/libgo/go/cmd/go/internal/work/buildid.go b/libgo/go/cmd/go/internal/work/buildid.go index c7c07ed0186..fb57e912802 100644 --- a/libgo/go/cmd/go/internal/work/buildid.go +++ b/libgo/go/cmd/go/internal/work/buildid.go @@ -18,6 +18,7 @@ import ( "cmd/go/internal/load" "cmd/go/internal/str" "cmd/internal/buildid" + "cmd/internal/objabi" ) // Build IDs @@ -174,20 +175,29 @@ func (b *Builder) toolID(name string) string { return id } - cmdline := str.StringList(cfg.BuildToolexec, base.Tool(name), "-V=full") + path := base.Tool(name) + desc := "go tool " + name + + // Special case: undocumented -vettool overrides usual vet, for testing vet. + if name == "vet" && VetTool != "" { + path = VetTool + desc = VetTool + } + + cmdline := str.StringList(cfg.BuildToolexec, path, "-V=full") cmd := exec.Command(cmdline[0], cmdline[1:]...) cmd.Env = base.EnvForDir(cmd.Dir, os.Environ()) var stdout, stderr bytes.Buffer cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - base.Fatalf("go tool %s: %v\n%s%s", name, err, stdout.Bytes(), stderr.Bytes()) + base.Fatalf("%s: %v\n%s%s", desc, err, stdout.Bytes(), stderr.Bytes()) } line := stdout.String() f := strings.Fields(line) - if len(f) < 3 || f[0] != name || f[1] != "version" || f[2] == "devel" && !strings.HasPrefix(f[len(f)-1], "buildID=") { - base.Fatalf("go tool %s -V=full: unexpected output:\n\t%s", name, line) + if len(f) < 3 || f[0] != name && path != VetTool || f[1] != "version" || f[2] == "devel" && !strings.HasPrefix(f[len(f)-1], "buildID=") { + base.Fatalf("%s -V=full: unexpected output:\n\t%s", desc, line) } if f[2] == "devel" { // On the development branch, use the content ID part of the build ID. @@ -197,6 +207,11 @@ func (b *Builder) toolID(name string) string { id = f[2] } + // For the compiler, add any experiments. + if name == "compile" { + id += " " + objabi.Expstring() + } + b.id.Lock() b.toolIDCache[name] = id b.id.Unlock() @@ -301,11 +316,7 @@ func assemblerIsGas() bool { if err == nil { cmd := exec.Command(strings.TrimSpace(string(assembler)), "--version") out, err := cmd.Output() - if err == nil && strings.Contains(string(out), "GNU") { - return true - } else { - return false - } + return err == nil && strings.Contains(string(out), "GNU") } else { return false } @@ -480,7 +491,7 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID // already up-to-date, then to avoid a rebuild, report the package // as up-to-date as well. See "Build IDs" comment above. // TODO(rsc): Rewrite this code to use a TryCache func on the link action. - if target != "" && !cfg.BuildA && a.Mode == "build" && len(a.triggers) == 1 && a.triggers[0].Mode == "link" { + if target != "" && !cfg.BuildA && !b.NeedExport && a.Mode == "build" && len(a.triggers) == 1 && a.triggers[0].Mode == "link" { buildID, err := buildid.ReadFile(target) if err == nil { id := strings.Split(buildID, buildIDSeparator) @@ -499,6 +510,14 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID a.buildID = id[1] + buildIDSeparator + id[2] linkID := hashToString(b.linkActionID(a.triggers[0])) if id[0] == linkID { + // Best effort attempt to display output from the compile and link steps. + // If it doesn't work, it doesn't work: reusing the cached binary is more + // important than reprinting diagnostic information. + if c := cache.Default(); c != nil { + showStdout(b, c, a.actionID, "stdout") // compile output + showStdout(b, c, a.actionID, "link-stdout") // link output + } + // Poison a.Target to catch uses later in the build. a.Target = "DO NOT USE - main build pseudo-cache Target" a.built = "DO NOT USE - main build pseudo-cache built" @@ -516,13 +535,22 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID // We avoid the nested build ID problem in the previous special case // by recording the test results in the cache under the action ID half. if !cfg.BuildA && len(a.triggers) == 1 && a.triggers[0].TryCache != nil && a.triggers[0].TryCache(b, a.triggers[0]) { + // Best effort attempt to display output from the compile and link steps. + // If it doesn't work, it doesn't work: reusing the test result is more + // important than reprinting diagnostic information. + if c := cache.Default(); c != nil { + showStdout(b, c, a.Deps[0].actionID, "stdout") // compile output + showStdout(b, c, a.Deps[0].actionID, "link-stdout") // link output + } + + // Poison a.Target to catch uses later in the build. a.Target = "DO NOT USE - pseudo-cache Target" a.built = "DO NOT USE - pseudo-cache built" return true } - if b.ComputeStaleOnly { - // Invoked during go list only to compute and record staleness. + if b.IsCmdList { + // Invoked during go list to compute and record staleness. if p := a.Package; p != nil && !p.Stale { p.Stale = true if cfg.BuildA { @@ -554,22 +582,9 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID // but we're still happy to use results from the build artifact cache. if c := cache.Default(); c != nil { if !cfg.BuildA { - entry, err := c.Get(actionHash) - if err == nil { - file := c.OutputFile(entry.OutputID) - info, err1 := os.Stat(file) - buildID, err2 := buildid.ReadFile(file) - if err1 == nil && err2 == nil && info.Size() == entry.Size { - stdout, stdoutEntry, err := c.GetBytes(cache.Subkey(a.actionID, "stdout")) - if err == nil { - if len(stdout) > 0 { - if cfg.BuildX || cfg.BuildN { - b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList("cat", c.OutputFile(stdoutEntry.OutputID)))) - } - if !cfg.BuildN { - b.Print(string(stdout)) - } - } + if file, _, err := c.GetFile(actionHash); err == nil { + if buildID, err := buildid.ReadFile(file); err == nil { + if err := showStdout(b, c, a.actionID, "stdout"); err == nil { a.built = file a.Target = "DO NOT USE - using cache" a.buildID = buildID @@ -587,11 +602,24 @@ func (b *Builder) useCache(a *Action, p *load.Package, actionHash cache.ActionID a.output = []byte{} } - if b.ComputeStaleOnly { - return true + return false +} + +func showStdout(b *Builder, c *cache.Cache, actionID cache.ActionID, key string) error { + stdout, stdoutEntry, err := c.GetBytes(cache.Subkey(actionID, key)) + if err != nil { + return err } - return false + if len(stdout) > 0 { + if cfg.BuildX || cfg.BuildN { + b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList("cat", c.OutputFile(stdoutEntry.OutputID)))) + } + if !cfg.BuildN { + b.Print(string(stdout)) + } + } + return nil } // flushOutput flushes the output being queued in a. @@ -618,6 +646,26 @@ func (b *Builder) updateBuildID(a *Action, target string, rewrite bool) error { } } + // Cache output from compile/link, even if we don't do the rest. + if c := cache.Default(); c != nil { + switch a.Mode { + case "build": + c.PutBytes(cache.Subkey(a.actionID, "stdout"), a.output) + case "link": + // Even though we don't cache the binary, cache the linker text output. + // We might notice that an installed binary is up-to-date but still + // want to pretend to have run the linker. + // Store it under the main package's action ID + // to make it easier to find when that's all we have. + for _, a1 := range a.Deps { + if p1 := a1.Package; p1 != nil && p1.Name == "main" { + c.PutBytes(cache.Subkey(a1.actionID, "link-stdout"), a.output) + break + } + } + } + } + // Find occurrences of old ID and compute new content-based ID. r, err := os.Open(target) if err != nil { @@ -675,11 +723,16 @@ func (b *Builder) updateBuildID(a *Action, target string, rewrite bool) error { panic("internal error: a.output not set") } outputID, _, err := c.Put(a.actionID, r) + r.Close() if err == nil && cfg.BuildX { b.Showcmd("", "%s # internal", joinUnambiguously(str.StringList("cp", target, c.OutputFile(outputID)))) } - c.PutBytes(cache.Subkey(a.actionID, "stdout"), a.output) - r.Close() + if b.NeedExport { + if err != nil { + return err + } + a.Package.Export = c.OutputFile(outputID) + } } } diff --git a/libgo/go/cmd/go/internal/work/exec.go b/libgo/go/cmd/go/internal/work/exec.go index 5994dbc702f..84870e52ccc 100644 --- a/libgo/go/cmd/go/internal/work/exec.go +++ b/libgo/go/cmd/go/internal/work/exec.go @@ -14,6 +14,7 @@ import ( "io" "io/ioutil" "log" + "math/rand" "os" "os/exec" "path/filepath" @@ -53,7 +54,7 @@ func actionList(root *Action) []*Action { // do runs the action graph rooted at root. func (b *Builder) Do(root *Action) { - if c := cache.Default(); c != nil && !b.ComputeStaleOnly { + if c := cache.Default(); c != nil && !b.IsCmdList { // If we're doing real work, take time at the end to trim the cache. defer c.Trim() } @@ -195,10 +196,13 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch) fmt.Fprintf(h, "import %q\n", p.ImportPath) fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix) + if p.Internal.ForceLibrary { + fmt.Fprintf(h, "forcelibrary\n") + } if len(p.CgoFiles)+len(p.SwigFiles) > 0 { fmt.Fprintf(h, "cgo %q\n", b.toolID("cgo")) - cppflags, cflags, cxxflags, fflags, _, _ := b.CFlags(p) - fmt.Fprintf(h, "CC=%q %q %q\n", b.ccExe(), cppflags, cflags) + 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) } @@ -295,40 +299,93 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { return h.Sum() } +// needCgoHdr reports whether the actions triggered by this one +// expect to be able to access the cgo-generated header file. +func (b *Builder) needCgoHdr(a *Action) bool { + // If this build triggers a header install, run cgo to get the header. + if !b.IsCmdList && (a.Package.UsesCgo() || a.Package.UsesSwig()) && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") { + for _, t1 := range a.triggers { + if t1.Mode == "install header" { + return true + } + } + for _, t1 := range a.triggers { + for _, t2 := range t1.triggers { + if t2.Mode == "install header" { + return true + } + } + } + } + return false +} + +// allowedVersion reports whether the version v is an allowed version of go +// (one that we can compile). +// v is known to be of the form "1.23". +func allowedVersion(v string) bool { + // Special case: no requirement. + if v == "" { + return true + } + // Special case "1.0" means "go1", which is OK. + if v == "1.0" { + return true + } + // Otherwise look through release tags of form "go1.23" for one that matches. + for _, tag := range cfg.BuildContext.ReleaseTags { + if strings.HasPrefix(tag, "go") && tag[2:] == v { + return true + } + } + return false +} + +const ( + needBuild uint32 = 1 << iota + needCgoHdr + needVet + needCompiledGoFiles + needStale +) + // build is the action for building a single package. // Note that any new influence on this logic must be reported in b.buildActionID above as well. func (b *Builder) build(a *Action) (err error) { p := a.Package + + bit := func(x uint32, b bool) uint32 { + if b { + return x + } + return 0 + } + cached := false + need := bit(needBuild, !b.IsCmdList || b.NeedExport) | + bit(needCgoHdr, b.needCgoHdr(a)) | + bit(needVet, a.needVet) | + bit(needCompiledGoFiles, b.NeedCompiledGoFiles) + if !p.BinaryOnly { if b.useCache(a, p, b.buildActionID(a), p.Target) { - // If this build triggers a header install, run cgo to get the header. - // TODO(rsc): Once we can cache multiple file outputs from an action, - // the header should be cached, and then this awful test can be deleted. - // Need to look for install header actions depending on this action, - // or depending on a link that depends on this action. - needHeader := false - if (a.Package.UsesCgo() || a.Package.UsesSwig()) && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") { - for _, t1 := range a.triggers { - if t1.Mode == "install header" { - needHeader = true - goto CheckedHeader - } - } - for _, t1 := range a.triggers { - for _, t2 := range t1.triggers { - if t2.Mode == "install header" { - needHeader = true - goto CheckedHeader - } - } - } + // We found the main output in the cache. + // If we don't need any other outputs, we can stop. + need &^= needBuild + if b.NeedExport { + p.Export = a.built } - CheckedHeader: - if b.ComputeStaleOnly || !a.needVet && !needHeader { - return nil + if need&needCompiledGoFiles != 0 && b.loadCachedGoFiles(a) { + need &^= needCompiledGoFiles } + // Otherwise, we need to write files to a.Objdir (needVet, needCgoHdr). + // Remember that we might have them in cache + // and check again after we create a.Objdir. cached = true + a.output = []byte{} // start saving output in case we miss any cache results + } + if need == 0 { + return nil } defer b.flushOutput(a) } @@ -337,6 +394,9 @@ func (b *Builder) build(a *Action) (err error) { if err != nil && err != errPrintedOutput { err = fmt.Errorf("go build %s: %v", a.Package.ImportPath, err) } + if err != nil && b.IsCmdList && b.NeedError && p.Error == nil { + p.Error = &load.PackageError{Err: err.Error()} + } }() if cfg.BuildN { // In -n mode, print a banner between packages. @@ -356,17 +416,24 @@ func (b *Builder) build(a *Action) (err error) { if err == nil { a.built = a.Package.Target a.Target = a.Package.Target + if b.NeedExport { + a.Package.Export = a.Package.Target + } a.buildID = b.fileHash(a.Package.Target) a.Package.Stale = false a.Package.StaleReason = "binary-only package" return nil } - if b.ComputeStaleOnly { - a.Package.Stale = true - a.Package.StaleReason = "missing or invalid binary-only package" + a.Package.Stale = true + a.Package.StaleReason = "missing or invalid binary-only package" + if b.IsCmdList { return nil } - return fmt.Errorf("missing or invalid binary-only package") + return fmt.Errorf("missing or invalid binary-only package; expected file %q", a.Package.Target) + } + + if p.Module != nil && !allowedVersion(p.Module.GoVersion) { + return fmt.Errorf("module requires Go %s", p.Module.GoVersion) } if err := b.Mkdir(a.Objdir); err != nil { @@ -374,6 +441,23 @@ func (b *Builder) build(a *Action) (err error) { } objdir := a.Objdir + if cached { + if need&needCgoHdr != 0 && b.loadCachedCgoHdr(a) { + need &^= needCgoHdr + } + + // Load cached vet config, but only if that's all we have left + // (need == needVet, not testing just the one bit). + // If we are going to do a full build anyway, + // we're going to regenerate the files below anyway. + if need == needVet && b.loadCachedVet(a) { + need &^= needVet + } + if need == 0 { + return nil + } + } + // make target directory dir, _ := filepath.Split(a.Target) if dir != "" { @@ -382,13 +466,12 @@ func (b *Builder) build(a *Action) (err error) { } } - var gofiles, cgofiles, cfiles, sfiles, cxxfiles, objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string - - gofiles = append(gofiles, a.Package.GoFiles...) - cgofiles = append(cgofiles, a.Package.CgoFiles...) - cfiles = append(cfiles, a.Package.CFiles...) - sfiles = append(sfiles, a.Package.SFiles...) - cxxfiles = append(cxxfiles, a.Package.CXXFiles...) + gofiles := str.StringList(a.Package.GoFiles) + cgofiles := str.StringList(a.Package.CgoFiles) + cfiles := str.StringList(a.Package.CFiles) + sfiles := str.StringList(a.Package.SFiles) + cxxfiles := str.StringList(a.Package.CXXFiles) + var objects, cgoObjects, pcCFLAGS, pcLDFLAGS []string if a.Package.UsesCgo() || a.Package.UsesSwig() { if pcCFLAGS, pcLDFLAGS, err = b.getPkgConfigFlags(a.Package); err != nil { @@ -432,7 +515,7 @@ func (b *Builder) build(a *Action) (err error) { // Not covering this file. continue } - if err := b.cover(a, coverFile, sourceFile, 0666, cover.Var); err != nil { + if err := b.cover(a, coverFile, sourceFile, cover.Var); err != nil { return err } if i < len(gofiles) { @@ -488,10 +571,16 @@ func (b *Builder) build(a *Action) (err error) { } cgoObjects = append(cgoObjects, outObj...) gofiles = append(gofiles, outGo...) + + switch cfg.BuildBuildmode { + case "c-archive", "c-shared": + b.cacheCgoHdr(a) + } } - if cached && !a.needVet { - return nil - } + b.cacheGofiles(a, gofiles) + + // Running cgo generated the cgo header. + need &^= needCgoHdr // Sanity check only, since Package.load already checked as well. if len(gofiles) == 0 { @@ -499,26 +588,19 @@ func (b *Builder) build(a *Action) (err error) { } // Prepare Go vet config if needed. - var vcfg *vetConfig - if a.needVet { - // Pass list of absolute paths to vet, - // so that vet's error messages will use absolute paths, - // so that we can reformat them relative to the directory - // in which the go command is invoked. - vcfg = &vetConfig{ - Compiler: cfg.BuildToolchainName, - Dir: a.Package.Dir, - GoFiles: mkAbsFiles(a.Package.Dir, gofiles), - ImportPath: a.Package.ImportPath, - ImportMap: make(map[string]string), - PackageFile: make(map[string]string), - Standard: make(map[string]bool), - } - a.vetCfg = vcfg - for i, raw := range a.Package.Internal.RawImports { - final := a.Package.Imports[i] - vcfg.ImportMap[raw] = final + if need&needVet != 0 { + buildVetConfig(a, gofiles) + need &^= needVet + } + if need&needCompiledGoFiles != 0 { + if !b.loadCachedGoFiles(a) { + return fmt.Errorf("failed to cache compiled Go files") } + need &^= needCompiledGoFiles + } + if need == 0 { + // Nothing left to do. + return nil } // Prepare Go import config. @@ -529,24 +611,12 @@ func (b *Builder) build(a *Action) (err error) { // except when it doesn't. var icfg bytes.Buffer fmt.Fprintf(&icfg, "# import config\n") - for i, raw := range a.Package.Internal.RawImports { final := a.Package.Imports[i] if final != raw { fmt.Fprintf(&icfg, "importmap %s=%s\n", raw, final) } } - - // Compute the list of mapped imports in the vet config - // so that we can add any missing mappings below. - var vcfgMapped map[string]bool - if vcfg != nil { - vcfgMapped = make(map[string]bool) - for _, p := range vcfg.ImportMap { - vcfgMapped[p] = true - } - } - for _, a1 := range a.Deps { p1 := a1.Package if p1 == nil || p1.ImportPath == "" { @@ -555,33 +625,20 @@ func (b *Builder) build(a *Action) (err error) { if a1.built != "" { fmt.Fprintf(&icfg, "packagefile %s=%s\n", p1.ImportPath, a1.built) } - if vcfg != nil { - // Add import mapping if needed - // (for imports like "runtime/cgo" that appear only in generated code). - if !vcfgMapped[p1.ImportPath] { - vcfg.ImportMap[p1.ImportPath] = p1.ImportPath - } - if a1.built != "" { - vcfg.PackageFile[p1.ImportPath] = a1.built - } - if p1.Standard { - vcfg.Standard[p1.ImportPath] = true - } - } } - if cached { - // The cached package file is OK, so we don't need to run the compile. - // We've only going through the motions to prepare the vet configuration, - // which is now complete. - return nil + if p.Internal.BuildInfo != "" && cfg.ModulesEnabled { + if err := b.writeFile(objdir+"_gomod_.go", load.ModInfoProg(p.Internal.BuildInfo)); err != nil { + return err + } + gofiles = append(gofiles, objdir+"_gomod_.go") } // Compile Go. objpkg := objdir + "_pkg_.a" ofile, out, err := BuildToolchain.gc(b, a, objpkg, icfg.Bytes(), len(sfiles) > 0, gofiles) if len(out) > 0 { - b.showOutput(a, a.Package.Dir, a.Package.ImportPath, b.processOutput(out)) + b.showOutput(a, a.Package.Dir, a.Package.Desc(), b.processOutput(out)) if err != nil { return errPrintedOutput } @@ -604,17 +661,17 @@ func (b *Builder) build(a *Action) (err error) { switch { case strings.HasSuffix(name, _goos_goarch): targ := file[:len(name)-len(_goos_goarch)] + "_GOOS_GOARCH." + ext - if err := b.copyFile(a, objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil { + if err := b.copyFile(objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil { return err } case strings.HasSuffix(name, _goarch): targ := file[:len(name)-len(_goarch)] + "_GOARCH." + ext - if err := b.copyFile(a, objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil { + if err := b.copyFile(objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil { return err } case strings.HasSuffix(name, _goos): targ := file[:len(name)-len(_goos)] + "_GOOS." + ext - if err := b.copyFile(a, objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil { + if err := b.copyFile(objdir+targ, filepath.Join(a.Package.Dir, file), 0666, true); err != nil { return err } } @@ -638,7 +695,7 @@ func (b *Builder) build(a *Action) (err error) { } // For gccgo on ELF systems, we write the build ID as an assembler file. - // This lets us set the the SHF_EXCLUDE flag. + // This lets us set the SHF_EXCLUDE flag. // This is read by readGccgoArchive in cmd/internal/buildid/buildid.go. if a.buildID != "" && cfg.BuildToolchainName == "gccgo" { switch cfg.Goos { @@ -695,16 +752,189 @@ func (b *Builder) build(a *Action) (err error) { return nil } -type vetConfig struct { - Compiler string - Dir string - GoFiles []string - ImportMap map[string]string - PackageFile map[string]string - Standard map[string]bool - ImportPath string +func (b *Builder) cacheObjdirFile(a *Action, c *cache.Cache, name string) error { + f, err := os.Open(a.Objdir + name) + if err != nil { + return err + } + defer f.Close() + _, _, err = c.Put(cache.Subkey(a.actionID, name), f) + return err +} - SucceedOnTypecheckFailure bool +func (b *Builder) findCachedObjdirFile(a *Action, c *cache.Cache, name string) (string, error) { + file, _, err := c.GetFile(cache.Subkey(a.actionID, name)) + if err != nil { + return "", err + } + return file, nil +} + +func (b *Builder) loadCachedObjdirFile(a *Action, c *cache.Cache, name string) error { + cached, err := b.findCachedObjdirFile(a, c, name) + if err != nil { + return err + } + return b.copyFile(a.Objdir+name, cached, 0666, true) +} + +func (b *Builder) cacheCgoHdr(a *Action) { + c := cache.Default() + if c == nil { + return + } + b.cacheObjdirFile(a, c, "_cgo_install.h") +} + +func (b *Builder) loadCachedCgoHdr(a *Action) bool { + c := cache.Default() + if c == nil { + return false + } + err := b.loadCachedObjdirFile(a, c, "_cgo_install.h") + return err == nil +} + +func (b *Builder) cacheGofiles(a *Action, gofiles []string) { + c := cache.Default() + if c == nil { + return + } + var buf bytes.Buffer + for _, file := range gofiles { + if !strings.HasPrefix(file, a.Objdir) { + // not generated + buf.WriteString("./") + buf.WriteString(file) + buf.WriteString("\n") + continue + } + name := file[len(a.Objdir):] + buf.WriteString(name) + buf.WriteString("\n") + if err := b.cacheObjdirFile(a, c, name); err != nil { + return + } + } + c.PutBytes(cache.Subkey(a.actionID, "gofiles"), buf.Bytes()) +} + +func (b *Builder) loadCachedVet(a *Action) bool { + c := cache.Default() + if c == nil { + return false + } + list, _, err := c.GetBytes(cache.Subkey(a.actionID, "gofiles")) + if err != nil { + return false + } + var gofiles []string + for _, name := range strings.Split(string(list), "\n") { + if name == "" { // end of list + continue + } + if strings.HasPrefix(name, "./") { + gofiles = append(gofiles, name[2:]) + continue + } + if err := b.loadCachedObjdirFile(a, c, name); err != nil { + return false + } + gofiles = append(gofiles, a.Objdir+name) + } + buildVetConfig(a, gofiles) + return true +} + +func (b *Builder) loadCachedGoFiles(a *Action) bool { + c := cache.Default() + if c == nil { + return false + } + list, _, err := c.GetBytes(cache.Subkey(a.actionID, "gofiles")) + if err != nil { + return false + } + var files []string + for _, name := range strings.Split(string(list), "\n") { + if name == "" { // end of list + continue + } + if strings.HasPrefix(name, "./") { + files = append(files, name[len("./"):]) + continue + } + file, err := b.findCachedObjdirFile(a, c, name) + if err != nil { + return false + } + files = append(files, file) + } + a.Package.CompiledGoFiles = files + return true +} + +// vetConfig is the configuration passed to vet describing a single package. +type vetConfig struct { + Compiler string // compiler name (gc, gccgo) + Dir string // directory containing package + ImportPath string // canonical import path ("package path") + GoFiles []string // absolute paths to package source files + + ImportMap map[string]string // map import path in source code to package path + PackageFile map[string]string // map package path to .a file with export data + Standard map[string]bool // map package path to whether it's in the standard library + PackageVetx map[string]string // map package path to vetx data from earlier vet run + VetxOnly bool // only compute vetx data; don't report detected problems + VetxOutput string // write vetx data to this output file + + SucceedOnTypecheckFailure bool // awful hack; see #18395 and below +} + +func buildVetConfig(a *Action, gofiles []string) { + // Pass list of absolute paths to vet, + // so that vet's error messages will use absolute paths, + // so that we can reformat them relative to the directory + // in which the go command is invoked. + vcfg := &vetConfig{ + Compiler: cfg.BuildToolchainName, + Dir: a.Package.Dir, + GoFiles: mkAbsFiles(a.Package.Dir, gofiles), + ImportPath: a.Package.ImportPath, + ImportMap: make(map[string]string), + PackageFile: make(map[string]string), + Standard: make(map[string]bool), + } + a.vetCfg = vcfg + for i, raw := range a.Package.Internal.RawImports { + final := a.Package.Imports[i] + vcfg.ImportMap[raw] = final + } + + // Compute the list of mapped imports in the vet config + // so that we can add any missing mappings below. + vcfgMapped := make(map[string]bool) + for _, p := range vcfg.ImportMap { + vcfgMapped[p] = true + } + + for _, a1 := range a.Deps { + p1 := a1.Package + if p1 == nil || p1.ImportPath == "" { + continue + } + // Add import mapping if needed + // (for imports like "runtime/cgo" that appear only in generated code). + if !vcfgMapped[p1.ImportPath] { + vcfg.ImportMap[p1.ImportPath] = p1.ImportPath + } + if a1.built != "" { + vcfg.PackageFile[p1.ImportPath] = a1.built + } + if p1.Standard { + vcfg.Standard[p1.ImportPath] = true + } + } } // VetTool is the path to an alternate vet tool binary. @@ -719,13 +949,51 @@ func (b *Builder) vet(a *Action) error { // a.Deps[0] is the build of the package being vetted. // a.Deps[1] is the build of the "fmt" package. + a.Failed = false // vet of dependency may have failed but we can still succeed + + if a.Deps[0].Failed { + // The build of the package has failed. Skip vet check. + // Vet could return export data for non-typecheck errors, + // but we ignore it because the package cannot be compiled. + return nil + } + vcfg := a.Deps[0].vetCfg if vcfg == nil { // Vet config should only be missing if the build failed. - if !a.Deps[0].Failed { - return fmt.Errorf("vet config not found") + return fmt.Errorf("vet config not found") + } + + vcfg.VetxOnly = a.VetxOnly + vcfg.VetxOutput = a.Objdir + "vet.out" + vcfg.PackageVetx = make(map[string]string) + + h := cache.NewHash("vet " + a.Package.ImportPath) + fmt.Fprintf(h, "vet %q\n", b.toolID("vet")) + + // Note: We could decide that vet should compute export data for + // all analyses, in which case we don't need to include the flags here. + // But that would mean that if an analysis causes problems like + // unexpected crashes there would be no way to turn it off. + // It seems better to let the flags disable export analysis too. + fmt.Fprintf(h, "vetflags %q\n", VetFlags) + + fmt.Fprintf(h, "pkg %q\n", a.Deps[0].actionID) + for _, a1 := range a.Deps { + if a1.Mode == "vet" && a1.built != "" { + fmt.Fprintf(h, "vetout %q %s\n", a1.Package.ImportPath, b.fileHash(a1.built)) + vcfg.PackageVetx[a1.Package.ImportPath] = a1.built + } + } + key := cache.ActionID(h.Sum()) + + if vcfg.VetxOnly { + if c := cache.Default(); c != nil && !cfg.BuildA { + if file, _, err := c.GetFile(key); err == nil { + a.built = file + return nil + } } - return nil } if vcfg.ImportMap["fmt"] == "" { @@ -742,7 +1010,9 @@ func (b *Builder) vet(a *Action) error { // so at least for now assume the bug is in vet. // We know of at least #18395. // TODO(rsc,gri): Try to remove this for Go 1.11. - vcfg.SucceedOnTypecheckFailure = cfg.CmdName == "test" + // + // Disabled 2018-04-20. Let's see if we can do without it. + // vcfg.SucceedOnTypecheckFailure = cfg.CmdName == "test" js, err := json.MarshalIndent(vcfg, "", "\t") if err != nil { @@ -753,7 +1023,7 @@ func (b *Builder) vet(a *Action) error { return err } - var env []string + env := b.cCompilerEnv() if cfg.BuildToolchainName == "gccgo" { env = append(env, "GCCGO="+BuildToolchain.compiler()) } @@ -763,7 +1033,18 @@ func (b *Builder) vet(a *Action) error { if tool == "" { tool = base.Tool("vet") } - return b.run(a, p.Dir, p.ImportPath, env, cfg.BuildToolexec, tool, VetFlags, a.Objdir+"vet.cfg") + runErr := b.run(a, p.Dir, p.ImportPath, env, cfg.BuildToolexec, tool, VetFlags, a.Objdir+"vet.cfg") + + // If vet wrote export data, save it for input to future vets. + if f, err := os.Open(vcfg.VetxOutput); err == nil { + a.built = vcfg.VetxOutput + if c := cache.Default(); c != nil { + c.Put(key, f) + } + f.Close() + } + + return runErr } // linkActionID computes the action ID for a link action. @@ -849,7 +1130,7 @@ func (b *Builder) printLinkerConfig(h io.Writer, p *load.Package) { // link is the action for linking a single command. // Note that any new influence on this logic must be reported in b.linkActionID above as well. func (b *Builder) link(a *Action) (err error) { - if b.useCache(a, a.Package, b.linkActionID(a), a.Package.Target) { + if b.useCache(a, a.Package, b.linkActionID(a), a.Package.Target) || b.IsCmdList { return nil } defer b.flushOutput(a) @@ -886,11 +1167,11 @@ func (b *Builder) link(a *Action) (err error) { // We still call updateBuildID to update a.buildID, which is important // for test result caching, but passing rewrite=false (final arg) // means we don't actually rewrite the binary, nor store the - // result into the cache. - // Not calling updateBuildID means we also don't insert these - // binaries into the build object cache. That's probably a net win: + // result into the cache. That's probably a net win: // less cache space wasted on large binaries we are not likely to // need again. (On the other hand it does make repeated go test slower.) + // It also makes repeated go run slower, which is a win in itself: + // we don't want people to treat go run like a scripting environment. if err := b.updateBuildID(a, a.Target, !a.Package.Internal.OmitDebug); err != nil { return err } @@ -922,36 +1203,64 @@ func (b *Builder) PkgconfigCmd() string { } // splitPkgConfigOutput parses the pkg-config output into a slice of -// flags. pkg-config always uses \ to escape special characters. -func splitPkgConfigOutput(out []byte) []string { +// flags. This implements the algorithm from pkgconf/libpkgconf/argvsplit.c. +func splitPkgConfigOutput(out []byte) ([]string, error) { if len(out) == 0 { - return nil + return nil, nil } var flags []string - flag := make([]byte, len(out)) - r, w := 0, 0 - for r < len(out) { - switch out[r] { - case ' ', '\t', '\r', '\n': - if w > 0 { - flags = append(flags, string(flag[:w])) + flag := make([]byte, 0, len(out)) + escaped := false + quote := byte(0) + + for _, c := range out { + if escaped { + if quote != 0 { + switch c { + case '$', '`', '"', '\\': + default: + flag = append(flag, '\\') + } + flag = append(flag, c) + } else { + flag = append(flag, c) } - w = 0 - case '\\': - r++ - fallthrough - default: - if r < len(out) { - flag[w] = out[r] - w++ + escaped = false + } else if quote != 0 { + if c == quote { + quote = 0 + } else { + switch c { + case '\\': + escaped = true + default: + flag = append(flag, c) + } } + } else if strings.IndexByte(" \t\n\v\f\r", c) < 0 { + switch c { + case '\\': + escaped = true + case '\'', '"': + quote = c + default: + flag = append(flag, c) + } + } else if len(flag) != 0 { + flags = append(flags, string(flag)) + flag = flag[:0] } - r++ } - if w > 0 { - flags = append(flags, string(flag[:w])) + if escaped { + return nil, errors.New("broken character escaping in pkgconf output ") } - return flags + if quote != 0 { + return nil, errors.New("unterminated quoted string in pkgconf output ") + } else if len(flag) != 0 { + flags = append(flags, string(flag)) + } + + return flags, nil } // Calls pkg-config if needed and returns the cflags/ldflags needed to build the package. @@ -976,21 +1285,24 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, } } var out []byte - out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs) + out, err = b.runOut(p.Dir, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs) if err != nil { - b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+strings.Join(pkgs, " "), string(out)) + b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out)) b.Print(err.Error() + "\n") return nil, nil, errPrintedOutput } if len(out) > 0 { - cflags = splitPkgConfigOutput(out) + cflags, err = splitPkgConfigOutput(out) + if err != nil { + return nil, nil, err + } if err := checkCompilerFlags("CFLAGS", "pkg-config --cflags", cflags); err != nil { return nil, nil, err } } - out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs) + out, err = b.runOut(p.Dir, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs) if err != nil { - b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+strings.Join(pkgs, " "), string(out)) + b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+" -- "+strings.Join(pkgs, " "), string(out)) b.Print(err.Error() + "\n") return nil, nil, errPrintedOutput } @@ -1051,7 +1363,7 @@ func (b *Builder) linkSharedActionID(a *Action) cache.ActionID { } func (b *Builder) linkShared(a *Action) (err error) { - if b.useCache(a, nil, b.linkSharedActionID(a), a.Target) { + if b.useCache(a, nil, b.linkSharedActionID(a), a.Target) || b.IsCmdList { return nil } defer b.flushOutput(a) @@ -1096,7 +1408,9 @@ func BuildInstallFunc(b *Builder, a *Action) (err error) { // so the built target is not in the a1.Objdir tree that b.cleanup(a1) removes. if a1.built == a.Target { a.built = a.Target - b.cleanup(a1) + if !a.buggyInstall { + b.cleanup(a1) + } // Whether we're smart enough to avoid a complete rebuild // depends on exactly what the staleness and rebuild algorithms // are, as well as potentially the state of the Go build cache. @@ -1115,13 +1429,17 @@ func BuildInstallFunc(b *Builder, a *Action) (err error) { // We want to hide that awful detail as much as possible, so don't // advertise it by touching the mtimes (usually the libraries are up // to date). - if !a.buggyInstall && !b.ComputeStaleOnly { + if !a.buggyInstall && !b.IsCmdList { now := time.Now() os.Chtimes(a.Target, now, now) } return nil } - if b.ComputeStaleOnly { + + // If we're building for go list -export, + // never install anything; just keep the cache reference. + if b.IsCmdList { + a.built = a1.built return nil } @@ -1146,9 +1464,11 @@ func BuildInstallFunc(b *Builder, a *Action) (err error) { } } - defer b.cleanup(a1) + if !a.buggyInstall { + defer b.cleanup(a1) + } - return b.moveOrCopyFile(a, a.Target, a1.built, perm, false) + return b.moveOrCopyFile(a.Target, a1.built, perm, false) } // cleanup removes a's object dir to keep the amount of @@ -1158,14 +1478,18 @@ func BuildInstallFunc(b *Builder, a *Action) (err error) { func (b *Builder) cleanup(a *Action) { if !cfg.BuildWork { if cfg.BuildX { - b.Showcmd("", "rm -r %s", a.Objdir) + // Don't say we are removing the directory if + // we never created it. + if _, err := os.Stat(a.Objdir); err == nil || cfg.BuildN { + b.Showcmd("", "rm -r %s", a.Objdir) + } } os.RemoveAll(a.Objdir) } } // moveOrCopyFile is like 'mv src dst' or 'cp src dst'. -func (b *Builder) moveOrCopyFile(a *Action, dst, src string, perm os.FileMode, force bool) error { +func (b *Builder) moveOrCopyFile(dst, src string, perm os.FileMode, force bool) error { if cfg.BuildN { b.Showcmd("", "mv %s %s", src, dst) return nil @@ -1176,7 +1500,7 @@ func (b *Builder) moveOrCopyFile(a *Action, dst, src string, perm os.FileMode, f // If the source is in the build cache, we need to copy it. if strings.HasPrefix(src, cache.DefaultDir()) { - return b.copyFile(a, dst, src, perm, force) + return b.copyFile(dst, src, perm, force) } // On Windows, always copy the file, so that we respect the NTFS @@ -1184,7 +1508,7 @@ func (b *Builder) moveOrCopyFile(a *Action, dst, src string, perm os.FileMode, f // What matters here is not cfg.Goos (the system we are building // for) but runtime.GOOS (the system we are building on). if runtime.GOOS == "windows" { - return b.copyFile(a, dst, src, perm, force) + return b.copyFile(dst, src, perm, force) } // If the destination directory has the group sticky bit set, @@ -1192,7 +1516,7 @@ func (b *Builder) moveOrCopyFile(a *Action, dst, src string, perm os.FileMode, f // https://golang.org/issue/18878 if fi, err := os.Stat(filepath.Dir(dst)); err == nil { if fi.IsDir() && (fi.Mode()&os.ModeSetgid) != 0 { - return b.copyFile(a, dst, src, perm, force) + return b.copyFile(dst, src, perm, force) } } @@ -1222,11 +1546,11 @@ func (b *Builder) moveOrCopyFile(a *Action, dst, src string, perm os.FileMode, f } } - return b.copyFile(a, dst, src, perm, force) + return b.copyFile(dst, src, perm, force) } // copyFile is like 'cp src dst'. -func (b *Builder) copyFile(a *Action, dst, src string, perm os.FileMode, force bool) error { +func (b *Builder) copyFile(dst, src string, perm os.FileMode, force bool) error { if cfg.BuildN || cfg.BuildX { b.Showcmd("", "cp %s %s", src, dst) if cfg.BuildN { @@ -1317,12 +1641,12 @@ func (b *Builder) installHeader(a *Action) error { } } - return b.moveOrCopyFile(a, a.Target, src, 0666, true) + return b.moveOrCopyFile(a.Target, src, 0666, true) } // cover runs, in effect, // go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go -func (b *Builder) cover(a *Action, dst, src string, perm os.FileMode, varName string) error { +func (b *Builder) cover(a *Action, dst, src string, varName string) error { return b.run(a, a.Objdir, "cover "+a.Package.ImportPath, nil, cfg.BuildToolexec, base.Tool("cover"), @@ -1344,6 +1668,7 @@ var objectMagic = [][]byte{ {0x00, 0x00, 0x01, 0xEB}, // Plan 9 i386 {0x00, 0x00, 0x8a, 0x97}, // Plan 9 amd64 {0x00, 0x00, 0x06, 0x47}, // Plan 9 arm + {0x00, 0x61, 0x73, 0x6D}, // WASM {0x01, 0xDF}, // XCOFF32 {0x01, 0xF7}, // XCOFF64 } @@ -1389,11 +1714,11 @@ func mayberemovefile(s string) { func (b *Builder) fmtcmd(dir string, format string, args ...interface{}) string { cmd := fmt.Sprintf(format, args...) if dir != "" && dir != "/" { - to := "." + dot := " ." if dir[len(dir)-1] == filepath.Separator { - to += string(filepath.Separator) + dot += string(filepath.Separator) } - cmd = strings.Replace(" "+cmd, " "+dir, " "+to, -1)[1:] + cmd = strings.Replace(" "+cmd, " "+dir, dot, -1)[1:] if b.scriptDir != dir { b.scriptDir = dir cmd = "cd " + dir + "\n" + cmd @@ -1472,7 +1797,7 @@ var cgoTypeSigRe = regexp.MustCompile(`\b_C2?(type|func|var|macro)_\B`) // If the command fails, run prints information about the failure // and returns a non-nil error. func (b *Builder) run(a *Action, dir string, desc string, env []string, cmdargs ...interface{}) error { - out, err := b.runOut(dir, desc, env, cmdargs...) + out, err := b.runOut(dir, env, cmdargs...) if len(out) > 0 { if desc == "" { desc = b.fmtcmd(dir, "%s", strings.Join(str.StringList(cmdargs...), " ")) @@ -1504,7 +1829,7 @@ func (b *Builder) processOutput(out []byte) string { // runOut runs the command given by cmdline in the directory dir. // It returns the command output and any errors that occurred. -func (b *Builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) { +func (b *Builder) runOut(dir string, env []string, cmdargs ...interface{}) ([]byte, error) { cmdline := str.StringList(cmdargs...) for _, arg := range cmdline { @@ -1540,6 +1865,8 @@ func (b *Builder) runOut(dir string, desc string, env []string, cmdargs ...inter cmd := exec.Command(cmdline[0], cmdline[1:]...) cmd.Stdout = &buf cmd.Stderr = &buf + cleanup := passLongArgsInResponseFiles(cmd) + defer cleanup() cmd.Dir = dir cmd.Env = base.MergeEnvLists(env, base.EnvForDir(cmd.Dir, os.Environ())) err := cmd.Run() @@ -1576,6 +1903,13 @@ func joinUnambiguously(a []string) string { return buf.String() } +// cCompilerEnv returns environment variables to set when running the +// C compiler. This is needed to disable escape codes in clang error +// messages that confuse tools like cgo. +func (b *Builder) cCompilerEnv() []string { + return []string{"TERM=dumb"} +} + // mkdir makes the named directory. func (b *Builder) Mkdir(dir string) error { // Make Mkdir(a.Objdir) a no-op instead of an error when a.Objdir == "". @@ -1723,7 +2057,7 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s if !filepath.IsAbs(outfile) { outfile = filepath.Join(p.Dir, outfile) } - output, err := b.runOut(filepath.Dir(file), desc, nil, compiler, flags, "-o", outfile, "-c", filepath.Base(file)) + output, err := b.runOut(filepath.Dir(file), b.cCompilerEnv(), compiler, flags, "-o", outfile, "-c", filepath.Base(file)) if len(output) > 0 { // On FreeBSD 11, when we pass -g to clang 3.8 it // invokes its internal assembler with -dwarf-version=2. @@ -1763,7 +2097,7 @@ func (b *Builder) gccld(p *load.Package, objdir, out string, flags []string, obj } else { cmd = b.GccCmd(p.Dir, objdir) } - return b.run(nil, p.Dir, p.ImportPath, nil, cmd, "-o", out, objs, flags) + return b.run(nil, p.Dir, p.ImportPath, b.cCompilerEnv(), cmd, "-o", out, objs, flags) } // Grab these before main helpfully overwrites them. @@ -2068,7 +2402,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo // along to the host linker. At this point in the code, cgoLDFLAGS // consists of the original $CGO_LDFLAGS (unchecked) and all the // flags put together from source code (checked). - var cgoenv []string + cgoenv := b.cCompilerEnv() if len(cgoLDFLAGS) > 0 { flags := make([]string, len(cgoLDFLAGS)) for i, f := range cgoLDFLAGS { @@ -2195,7 +2529,15 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe // we need to use -pie for Linux/ARM to get accurate imported sym ldflags := cgoLDFLAGS if (cfg.Goarch == "arm" && cfg.Goos == "linux") || cfg.Goos == "android" { - ldflags = append(ldflags, "-pie") + // -static -pie doesn't make sense, and causes link errors. + // Issue 26197. + n := make([]string, 0, len(ldflags)) + for _, flag := range ldflags { + if flag != "-static" { + n = append(n, flag) + } + } + ldflags = append(n, "-pie") } if err := b.gccld(p, objdir, dynobj, ldflags, linkobj); err != nil { return err @@ -2206,7 +2548,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, p.Dir, p.ImportPath, nil, cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) + return b.run(a, p.Dir, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) } // Run SWIG on all SWIG input files. @@ -2256,7 +2598,7 @@ var ( ) func (b *Builder) swigDoVersionCheck() error { - out, err := b.runOut("", "", nil, "swig", "-version") + out, err := b.runOut("", nil, "swig", "-version") if err != nil { return err } @@ -2411,19 +2753,19 @@ func (b *Builder) swigOne(a *Action, p *load.Package, file, objdir string, pcCFL args = append(args, "-c++") } - out, err := b.runOut(p.Dir, p.ImportPath, nil, "swig", args, file) + out, err := b.runOut(p.Dir, nil, "swig", args, file) if err != nil { if len(out) > 0 { if bytes.Contains(out, []byte("-intgosize")) || bytes.Contains(out, []byte("-cgo")) { return "", "", errors.New("must have SWIG version >= 3.0.6") } - b.showOutput(a, p.Dir, p.ImportPath, b.processOutput(out)) // swig error + b.showOutput(a, p.Dir, p.Desc(), b.processOutput(out)) // swig error return "", "", errPrintedOutput } return "", "", err } if len(out) > 0 { - b.showOutput(a, p.Dir, p.ImportPath, b.processOutput(out)) // swig warning + b.showOutput(a, p.Dir, p.Desc(), b.processOutput(out)) // swig warning } // If the input was x.swig, the output is x.go in the objdir. @@ -2473,3 +2815,78 @@ func mkAbsFiles(dir string, files []string) []string { } return abs } + +// passLongArgsInResponseFiles modifies cmd on Windows such that, for +// certain programs, long arguments are passed in "response files", a +// file on disk with the arguments, with one arg per line. An actual +// argument starting with '@' means that the rest of the argument is +// a filename of arguments to expand. +// +// See Issue 18468. +func passLongArgsInResponseFiles(cmd *exec.Cmd) (cleanup func()) { + cleanup = func() {} // no cleanup by default + + var argLen int + for _, arg := range cmd.Args { + argLen += len(arg) + } + + // If we're not approaching 32KB of args, just pass args normally. + // (use 30KB instead to be conservative; not sure how accounting is done) + if !useResponseFile(cmd.Path, argLen) { + return + } + + tf, err := ioutil.TempFile("", "args") + if err != nil { + log.Fatalf("error writing long arguments to response file: %v", err) + } + cleanup = func() { os.Remove(tf.Name()) } + var buf bytes.Buffer + for _, arg := range cmd.Args[1:] { + fmt.Fprintf(&buf, "%s\n", arg) + } + if _, err := tf.Write(buf.Bytes()); err != nil { + tf.Close() + cleanup() + log.Fatalf("error writing long arguments to response file: %v", err) + } + if err := tf.Close(); err != nil { + cleanup() + log.Fatalf("error writing long arguments to response file: %v", err) + } + cmd.Args = []string{cmd.Args[0], "@" + tf.Name()} + return cleanup +} + +func useResponseFile(path string, argLen int) bool { + // Unless we're on Windows, don't use response files. + if runtime.GOOS != "windows" { + return false + } + + // Unless the program uses objabi.Flagparse, which understands + // response files, don't use response files. + // TODO: do we need more commands? asm? cgo? For now, no. + prog := strings.TrimSuffix(filepath.Base(path), ".exe") + switch prog { + case "compile", "link": + default: + return false + } + + // Windows has a limit of 32 KB arguments. To be conservative and not + // worry about whether that includes spaces or not, just use 30 KB. + if argLen > (30 << 10) { + return true + } + + // On the Go build system, use response files about 10% of the + // time, just to excercise this codepath. + isBuilder := os.Getenv("GO_BUILDER_NAME") != "" + if isBuilder && rand.Intn(10) == 0 { + return true + } + + return false +} diff --git a/libgo/go/cmd/go/internal/work/gc.go b/libgo/go/cmd/go/internal/work/gc.go index 71b5337939e..6e5333ccbc4 100644 --- a/libgo/go/cmd/go/internal/work/gc.go +++ b/libgo/go/cmd/go/internal/work/gc.go @@ -57,9 +57,14 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, a 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") { + compilingRuntime = true + } if compilingRuntime { - // runtime compiles with a special gc flag to emit - // additional reflect type data. + // runtime compiles with a special gc flag to check for + // memory allocations that are invalid in the runtime package, + // and to implement some special compiler pragmas. gcargs = append(gcargs, "-+") } @@ -70,7 +75,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, a extFiles := len(p.CgoFiles) + len(p.CFiles) + len(p.CXXFiles) + len(p.MFiles) + len(p.FFiles) + len(p.SFiles) + len(p.SysoFiles) + len(p.SwigFiles) + len(p.SwigCXXFiles) if p.Standard { switch p.ImportPath { - case "bytes", "internal/poll", "net", "os", "runtime/pprof", "sync", "syscall", "time": + case "bytes", "internal/poll", "net", "os", "runtime/pprof", "runtime/trace", "sync", "syscall", "time": extFiles++ } } @@ -84,7 +89,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, a gcargs = append(gcargs, "-buildid", a.buildID) } platform := cfg.Goos + "/" + cfg.Goarch - if p.Internal.OmitDebug || platform == "nacl/amd64p32" || platform == "darwin/arm" || platform == "darwin/arm64" || cfg.Goos == "plan9" { + if p.Internal.OmitDebug || platform == "nacl/amd64p32" || cfg.Goos == "plan9" || cfg.Goarch == "wasm" { gcargs = append(gcargs, "-dwarf=false") } if strings.HasPrefix(runtimeVersion, "go1") && !strings.Contains(os.Args[0], "go_bootstrap") { @@ -128,7 +133,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, a args = append(args, mkAbs(p.Dir, f)) } - output, err = b.runOut(p.Dir, p.ImportPath, nil, args...) + output, err = b.runOut(p.Dir, nil, args...) return ofile, output, err } @@ -228,6 +233,11 @@ func (gcToolchain) asm(b *Builder, a *Action, sfiles []string) ([]string, error) args = append(args, "-D", "GOMIPS_"+cfg.GOMIPS) } + if cfg.Goarch == "mips64" || cfg.Goarch == "mips64le" { + // Define GOMIPS64_value from cfg.GOMIPS64. + args = append(args, "-D", "GOMIPS64_"+cfg.GOMIPS64) + } + var ofiles []string for _, sfile := range sfiles { ofile := a.Objdir + sfile[:len(sfile)-len(".s")] + ".o" @@ -289,14 +299,14 @@ func (gcToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) er if cfg.BuildN { return nil } - if err := packInternal(b, absAfile, absOfiles); err != nil { - b.showOutput(a, p.Dir, p.ImportPath, err.Error()+"\n") + if err := packInternal(absAfile, absOfiles); err != nil { + b.showOutput(a, p.Dir, p.Desc(), err.Error()+"\n") return errPrintedOutput } return nil } -func packInternal(b *Builder, afile string, ofiles []string) error { +func packInternal(afile string, ofiles []string) error { dst, err := os.OpenFile(afile, os.O_WRONLY|os.O_APPEND, 0) if err != nil { return err diff --git a/libgo/go/cmd/go/internal/work/gccgo.go b/libgo/go/cmd/go/internal/work/gccgo.go index e8dab191478..7255748b5c3 100644 --- a/libgo/go/cmd/go/internal/work/gccgo.go +++ b/libgo/go/cmd/go/internal/work/gccgo.go @@ -87,7 +87,7 @@ func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg args = append(args, mkAbs(p.Dir, f)) } - output, err = b.runOut(p.Dir, p.ImportPath, nil, args) + output, err = b.runOut(p.Dir, nil, args) return ofile, output, err } @@ -270,7 +270,7 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string readAndRemoveCgoFlags := func(archive string) (string, error) { newID++ newArchive := root.Objdir + fmt.Sprintf("_pkg%d_.a", newID) - if err := b.copyFile(root, newArchive, archive, 0666, false); err != nil { + if err := b.copyFile(newArchive, archive, 0666, false); err != nil { return "", err } if cfg.BuildN { diff --git a/libgo/go/cmd/go/internal/work/init.go b/libgo/go/cmd/go/internal/work/init.go index c2beb3be6e7..de0cd4282b3 100644 --- a/libgo/go/cmd/go/internal/work/init.go +++ b/libgo/go/cmd/go/internal/work/init.go @@ -9,13 +9,16 @@ package work import ( "cmd/go/internal/base" "cmd/go/internal/cfg" + "cmd/go/internal/load" "flag" "fmt" "os" "path/filepath" + "strings" ) func BuildInit() { + load.ModInit() instrumentInit() buildModeInit() @@ -39,15 +42,20 @@ func instrumentInit() { fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0]) os.Exit(2) } - if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64") { + if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64" && cfg.Goarch != "arm64") { fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch) os.Exit(2) } - if cfg.Goarch != "amd64" || cfg.Goos != "linux" && cfg.Goos != "freebsd" && cfg.Goos != "darwin" && cfg.Goos != "windows" { - fmt.Fprintf(os.Stderr, "go %s: -race and -msan are only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) - os.Exit(2) + if cfg.BuildRace { + platform := cfg.Goos + "/" + cfg.Goarch + switch platform { + default: + fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) + os.Exit(2) + case "linux/amd64", "linux/ppc64le", "freebsd/amd64", "netbsd/amd64", "darwin/amd64", "windows/amd64": + // race supported on these platforms + } } - mode := "race" if cfg.BuildMSan { mode = "msan" @@ -83,6 +91,9 @@ func buildModeInit() { default: switch cfg.Goos { case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris": + if platform == "linux/ppc64" { + base.Fatalf("-buildmode=c-archive not supported on %s\n", platform) + } // Use -shared so that the result is // suitable for inclusion in a PIE or // shared library. @@ -101,7 +112,8 @@ func buildModeInit() { } else { switch platform { case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/s390x", - "android/amd64", "android/arm", "android/arm64", "android/386": + "android/amd64", "android/arm", "android/arm64", "android/386", + "freebsd/amd64": codegenArg = "-shared" case "darwin/amd64", "darwin/386": case "windows/amd64", "windows/386": @@ -144,7 +156,8 @@ func buildModeInit() { } else { switch platform { case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x", - "android/amd64", "android/arm", "android/arm64", "android/386": + "android/amd64", "android/arm", "android/arm64", "android/386", + "freebsd/amd64": codegenArg = "-shared" case "darwin/amd64": codegenArg = "-shared" @@ -220,4 +233,31 @@ func buildModeInit() { cfg.BuildContext.InstallSuffix += codegenArg[1:] } } + + switch cfg.BuildMod { + case "": + // ok + case "readonly", "vendor": + if load.ModLookup == nil && !inGOFLAGS("-mod") { + base.Fatalf("build flag -mod=%s only valid when using modules", cfg.BuildMod) + } + default: + base.Fatalf("-mod=%s not supported (can be '', 'readonly', or 'vendor')", cfg.BuildMod) + } +} + +func inGOFLAGS(flag string) bool { + for _, goflag := range base.GOFLAGS() { + name := goflag + if strings.HasPrefix(name, "--") { + name = name[1:] + } + if i := strings.Index(name, "="); i >= 0 { + name = name[:i] + } + if name == flag { + return true + } + } + return false } diff --git a/libgo/go/cmd/go/internal/work/security.go b/libgo/go/cmd/go/internal/work/security.go index 1b82af9c97c..d5d126123a4 100644 --- a/libgo/go/cmd/go/internal/work/security.go +++ b/libgo/go/cmd/go/internal/work/security.go @@ -112,6 +112,7 @@ var validCompilerFlags = []*regexp.Regexp{ re(`--sysroot=([^@\-].*)`), re(`-w`), re(`-x([^@\-].*)`), + re(`-v`), } var validCompilerFlagsWithNextArg = []string{ @@ -135,6 +136,7 @@ var validLinkerFlags = []*regexp.Regexp{ re(`-f(no-)?(pic|PIC|pie|PIE)`), re(`-f(no-)?openmp(-simd)?`), re(`-fsanitize=([^@\-].*)`), + re(`-flat_namespace`), re(`-g([^@\-].*)?`), re(`-headerpad_max_install_names`), re(`-m(abi|arch|cpu|fpu|tune)=([^@\-].*)`), @@ -150,6 +152,7 @@ var validLinkerFlags = []*regexp.Regexp{ re(`-shared`), re(`-?-static([-a-z0-9+]*)`), re(`-?-stdlib=([^@\-].*)`), + re(`-v`), // Note that any wildcards in -Wl need to exclude comma, // since -Wl splits its argument at commas and passes diff --git a/libgo/go/cmd/go/internal/work/security_test.go b/libgo/go/cmd/go/internal/work/security_test.go index c3a61b8e70b..d23b6eadff5 100644 --- a/libgo/go/cmd/go/internal/work/security_test.go +++ b/libgo/go/cmd/go/internal/work/security_test.go @@ -58,6 +58,7 @@ var goodCompilerFlags = [][]string{ {"-I", "世界"}, {"-framework", "Chocolate"}, {"-x", "c"}, + {"-v"}, } var badCompilerFlags = [][]string{ @@ -136,6 +137,7 @@ var goodLinkerFlags = [][]string{ {"-l", "世界"}, {"-L", "framework"}, {"-framework", "Chocolate"}, + {"-v"}, {"-Wl,-framework", "-Wl,Chocolate"}, {"-Wl,-framework,Chocolate"}, {"-Wl,-unresolved-symbols=ignore-all"}, diff --git a/libgo/go/cmd/go/main.go b/libgo/go/cmd/go/main.go index 7558e087673..14b435295ec 100644 --- a/libgo/go/cmd/go/main.go +++ b/libgo/go/cmd/go/main.go @@ -27,6 +27,10 @@ import ( "cmd/go/internal/get" "cmd/go/internal/help" "cmd/go/internal/list" + "cmd/go/internal/modcmd" + "cmd/go/internal/modfetch" + "cmd/go/internal/modget" + "cmd/go/internal/modload" "cmd/go/internal/run" "cmd/go/internal/test" "cmd/go/internal/tool" @@ -36,31 +40,37 @@ import ( ) func init() { - base.Commands = []*base.Command{ + base.Go.Commands = []*base.Command{ + bug.CmdBug, work.CmdBuild, clean.CmdClean, doc.CmdDoc, envcmd.CmdEnv, - bug.CmdBug, fix.CmdFix, fmtcmd.CmdFmt, generate.CmdGenerate, get.CmdGet, work.CmdInstall, list.CmdList, + modcmd.CmdMod, run.CmdRun, test.CmdTest, tool.CmdTool, version.CmdVersion, vet.CmdVet, - help.HelpC, help.HelpBuildmode, + help.HelpC, help.HelpCache, - help.HelpFileType, - help.HelpGopath, help.HelpEnvironment, + help.HelpFileType, + modload.HelpGoMod, + help.HelpGopath, + get.HelpGopathGet, + modfetch.HelpGoproxy, help.HelpImportPath, + modload.HelpModules, + modget.HelpModuleGet, help.HelpPackages, test.HelpTestflag, test.HelpTestfunc, @@ -78,6 +88,11 @@ func main() { base.Usage() } + if modload.MustUseModules { + // If running with modules force-enabled, change get now to change help message. + *get.CmdGet = *modget.CmdGet + } + cfg.CmdName = args[0] // for error messages if args[0] == "help" { help.Help(args[1:]) @@ -118,6 +133,46 @@ func main() { os.Exit(2) } + // TODO(rsc): Remove all these helper prints in Go 1.12. + switch args[0] { + case "mod": + if len(args) >= 2 { + flag := args[1] + if strings.HasPrefix(flag, "--") { + flag = flag[1:] + } + if i := strings.Index(flag, "="); i >= 0 { + flag = flag[:i] + } + switch flag { + case "-sync": + fmt.Fprintf(os.Stderr, "go: go mod -sync is now go mod tidy\n") + os.Exit(2) + case "-init", "-fix", "-graph", "-vendor", "-verify": + fmt.Fprintf(os.Stderr, "go: go mod %s is now go mod %s\n", flag, flag[1:]) + os.Exit(2) + case "-fmt", "-json", "-module", "-require", "-droprequire", "-replace", "-dropreplace", "-exclude", "-dropexclude": + fmt.Fprintf(os.Stderr, "go: go mod %s is now go mod edit %s\n", flag, flag) + os.Exit(2) + } + } + case "vendor": + fmt.Fprintf(os.Stderr, "go: vgo vendor is now go mod vendor\n") + os.Exit(2) + case "verify": + fmt.Fprintf(os.Stderr, "go: vgo verify is now go mod verify\n") + os.Exit(2) + } + + if args[0] == "get" { + // Replace get with module-aware get if appropriate. + // Note that if MustUseModules is true, this happened already above, + // but no harm in doing it again. + if modload.Init(); modload.Enabled() { + *get.CmdGet = *modget.CmdGet + } + } + // Set environment (GOOS, GOARCH, etc) explicitly. // In theory all the commands we invoke should have // the same default computation of these as we do, @@ -131,12 +186,36 @@ func main() { } } - for _, cmd := range base.Commands { - if cmd.Name() == args[0] && cmd.Runnable() { +BigCmdLoop: + for bigCmd := base.Go; ; { + for _, cmd := range bigCmd.Commands { + if cmd.Name() != args[0] { + continue + } + if len(cmd.Commands) > 0 { + bigCmd = cmd + args = args[1:] + if len(args) == 0 { + help.PrintUsage(os.Stderr, bigCmd) + base.SetExitStatus(2) + base.Exit() + } + if args[0] == "help" { + // Accept 'go mod help' and 'go mod help foo' for 'go help mod' and 'go help mod foo'. + help.Help(append(strings.Split(cfg.CmdName, " "), args[1:]...)) + return + } + cfg.CmdName += " " + args[0] + continue 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() } @@ -144,11 +223,14 @@ func main() { base.Exit() return } + helpArg := "" + if i := strings.LastIndex(cfg.CmdName, " "); i >= 0 { + helpArg = " " + cfg.CmdName[:i] + } + fmt.Fprintf(os.Stderr, "go %s: unknown command\nRun 'go help%s' for usage.\n", cfg.CmdName, helpArg) + base.SetExitStatus(2) + base.Exit() } - - fmt.Fprintf(os.Stderr, "go: unknown subcommand %q\nRun 'go help' for usage.\n", args[0]) - base.SetExitStatus(2) - base.Exit() } func init() { @@ -160,6 +242,6 @@ func mainUsage() { if len(os.Args) > 1 && os.Args[1] == "test" { test.Usage() } - help.PrintUsage(os.Stderr) + help.PrintUsage(os.Stderr, base.Go) os.Exit(2) } diff --git a/libgo/go/cmd/go/proxy_test.go b/libgo/go/cmd/go/proxy_test.go new file mode 100644 index 00000000000..212e5aa08f7 --- /dev/null +++ b/libgo/go/cmd/go/proxy_test.go @@ -0,0 +1,272 @@ +// 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_test + +import ( + "archive/zip" + "bytes" + "encoding/json" + "flag" + "fmt" + "io/ioutil" + "log" + "net" + "net/http" + "os" + "path/filepath" + "strings" + "sync" + "testing" + + "cmd/go/internal/modfetch" + "cmd/go/internal/modfetch/codehost" + "cmd/go/internal/module" + "cmd/go/internal/par" + "cmd/go/internal/semver" + "cmd/go/internal/txtar" +) + +var ( + proxyAddr = flag.String("proxy", "", "run proxy on this network address instead of running any tests") + proxyURL string +) + +var proxyOnce sync.Once + +// StartProxy starts the Go module proxy running on *proxyAddr (like "localhost:1234") +// and sets proxyURL to the GOPROXY setting to use to access the proxy. +// Subsequent calls are no-ops. +// +// The proxy serves from testdata/mod. See testdata/mod/README. +func StartProxy() { + proxyOnce.Do(func() { + fmt.Fprintf(os.Stderr, "go test proxy starting\n") + readModList() + addr := *proxyAddr + if addr == "" { + addr = "localhost:0" + } + l, err := net.Listen("tcp", addr) + if err != nil { + log.Fatal(err) + } + *proxyAddr = l.Addr().String() + proxyURL = "http://" + *proxyAddr + "/mod" + fmt.Fprintf(os.Stderr, "go test proxy running at GOPROXY=%s\n", proxyURL) + go func() { + log.Fatalf("go proxy: http.Serve: %v", http.Serve(l, http.HandlerFunc(proxyHandler))) + }() + }) +} + +var modList []module.Version + +func readModList() { + infos, err := ioutil.ReadDir("testdata/mod") + if err != nil { + log.Fatal(err) + } + for _, info := range infos { + name := info.Name() + if !strings.HasSuffix(name, ".txt") { + continue + } + name = strings.TrimSuffix(name, ".txt") + i := strings.LastIndex(name, "_v") + if i < 0 { + continue + } + encPath := strings.Replace(name[:i], "_", "/", -1) + path, err := module.DecodePath(encPath) + if err != nil { + fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err) + continue + } + encVers := name[i+1:] + vers, err := module.DecodeVersion(encVers) + if err != nil { + fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err) + continue + } + modList = append(modList, module.Version{Path: path, Version: vers}) + } +} + +var zipCache par.Cache + +// proxyHandler serves the Go module proxy protocol. +// See the proxy section of https://research.swtch.com/vgo-module. +func proxyHandler(w http.ResponseWriter, r *http.Request) { + if !strings.HasPrefix(r.URL.Path, "/mod/") { + http.NotFound(w, r) + return + } + path := strings.TrimPrefix(r.URL.Path, "/mod/") + i := strings.Index(path, "/@v/") + if i < 0 { + http.NotFound(w, r) + return + } + enc, file := path[:i], path[i+len("/@v/"):] + path, err := module.DecodePath(enc) + if err != nil { + fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err) + http.NotFound(w, r) + return + } + if file == "list" { + n := 0 + for _, m := range modList { + if m.Path == path && !modfetch.IsPseudoVersion(m.Version) { + if err := module.Check(m.Path, m.Version); err == nil { + fmt.Fprintf(w, "%s\n", m.Version) + n++ + } + } + } + if n == 0 { + http.NotFound(w, r) + } + return + } + + i = strings.LastIndex(file, ".") + if i < 0 { + http.NotFound(w, r) + return + } + encVers, ext := file[:i], file[i+1:] + vers, err := module.DecodeVersion(encVers) + if err != nil { + fmt.Fprintf(os.Stderr, "go proxy_test: %v\n", err) + http.NotFound(w, r) + return + } + + if codehost.AllHex(vers) { + var best string + // Convert commit hash (only) to known version. + // Use latest version in semver priority, to match similar logic + // in the repo-based module server (see modfetch.(*codeRepo).convert). + for _, m := range modList { + if m.Path == path && semver.Compare(best, m.Version) < 0 { + var hash string + if modfetch.IsPseudoVersion(m.Version) { + hash = m.Version[strings.LastIndex(m.Version, "-")+1:] + } else { + hash = findHash(m) + } + if strings.HasPrefix(hash, vers) || strings.HasPrefix(vers, hash) { + best = m.Version + } + } + } + if best != "" { + vers = best + } + } + + a := readArchive(path, vers) + if a == nil { + fmt.Fprintf(os.Stderr, "go proxy: no archive %s %s\n", path, vers) + http.Error(w, "cannot load archive", 500) + return + } + + switch ext { + case "info", "mod": + want := "." + ext + for _, f := range a.Files { + if f.Name == want { + w.Write(f.Data) + return + } + } + + case "zip": + type cached struct { + zip []byte + err error + } + c := zipCache.Do(a, func() interface{} { + var buf bytes.Buffer + z := zip.NewWriter(&buf) + for _, f := range a.Files { + if strings.HasPrefix(f.Name, ".") { + continue + } + zf, err := z.Create(path + "@" + vers + "/" + f.Name) + if err != nil { + return cached{nil, err} + } + if _, err := zf.Write(f.Data); err != nil { + return cached{nil, err} + } + } + if err := z.Close(); err != nil { + return cached{nil, err} + } + return cached{buf.Bytes(), nil} + }).(cached) + + if c.err != nil { + fmt.Fprintf(os.Stderr, "go proxy: %v\n", c.err) + http.Error(w, c.err.Error(), 500) + return + } + w.Write(c.zip) + return + + } + http.NotFound(w, r) +} + +func findHash(m module.Version) string { + a := readArchive(m.Path, m.Version) + if a == nil { + return "" + } + var data []byte + for _, f := range a.Files { + if f.Name == ".info" { + data = f.Data + break + } + } + var info struct{ Short string } + json.Unmarshal(data, &info) + return info.Short +} + +var archiveCache par.Cache + +var cmdGoDir, _ = os.Getwd() + +func readArchive(path, vers string) *txtar.Archive { + enc, err := module.EncodePath(path) + if err != nil { + fmt.Fprintf(os.Stderr, "go proxy: %v\n", err) + return nil + } + encVers, err := module.EncodeVersion(vers) + if err != nil { + fmt.Fprintf(os.Stderr, "go proxy: %v\n", err) + return nil + } + + prefix := strings.Replace(enc, "/", "_", -1) + name := filepath.Join(cmdGoDir, "testdata/mod", prefix+"_"+encVers+".txt") + a := archiveCache.Do(name, func() interface{} { + a, err := txtar.ParseFile(name) + if err != nil { + if testing.Verbose() || !os.IsNotExist(err) { + fmt.Fprintf(os.Stderr, "go proxy: %v\n", err) + } + a = nil + } + return a + }).(*txtar.Archive) + return a +} diff --git a/libgo/go/cmd/go/script_test.go b/libgo/go/cmd/go/script_test.go new file mode 100644 index 00000000000..02cb17b0452 --- /dev/null +++ b/libgo/go/cmd/go/script_test.go @@ -0,0 +1,905 @@ +// 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. + +// Script-driven tests. +// See testdata/script/README for an overview. + +package main_test + +import ( + "bytes" + "fmt" + "internal/testenv" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "regexp" + "runtime" + "strconv" + "strings" + "testing" + "time" + + "cmd/go/internal/imports" + "cmd/go/internal/par" + "cmd/go/internal/txtar" +) + +// TestScript runs the tests in testdata/script/*.txt. +func TestScript(t *testing.T) { + testenv.MustHaveGoBuild(t) + if skipExternal { + t.Skipf("skipping external tests on %s/%s", runtime.GOOS, runtime.GOARCH) + } + + files, err := filepath.Glob("testdata/script/*.txt") + if err != nil { + t.Fatal(err) + } + for _, file := range files { + file := file + name := strings.TrimSuffix(filepath.Base(file), ".txt") + t.Run(name, func(t *testing.T) { + t.Parallel() + ts := &testScript{t: t, name: name, file: file} + ts.setup() + if !*testWork { + defer removeAll(ts.workdir) + } + ts.run() + }) + } +} + +// 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 +} + +var extraEnvKeys = []string{ + "SYSTEMROOT", // must be preserved on Windows to find DLLs; golang.org/issue/25210 + "LD_LIBRARY_PATH", // must be preserved on Unix systems to find shared libraries + + // For gccgo testing. + "GO_TESTING_GOTOOLS", + "GCCGOTOOLDIR", +} + +// setup sets up the test execution temporary directory and environment. +func (ts *testScript) setup() { + StartProxy() + ts.workdir = filepath.Join(testTmpDir, "script-"+ts.name) + ts.check(os.MkdirAll(filepath.Join(ts.workdir, "tmp"), 0777)) + ts.check(os.MkdirAll(filepath.Join(ts.workdir, "gopath/src"), 0777)) + ts.cd = filepath.Join(ts.workdir, "gopath/src") + ts.env = []string{ + "WORK=" + ts.workdir, // must be first for ts.abbrev + "PATH=" + testBin + string(filepath.ListSeparator) + os.Getenv("PATH"), + homeEnvName() + "=/no-home", + "CCACHE_DISABLE=1", // ccache breaks with non-existent HOME + "GOARCH=" + runtime.GOARCH, + "GOCACHE=" + testGOCACHE, + "GOOS=" + runtime.GOOS, + "GOPATH=" + filepath.Join(ts.workdir, "gopath"), + "GOPROXY=" + proxyURL, + "GOROOT=" + testGOROOT, + tempEnvName() + "=" + filepath.Join(ts.workdir, "tmp"), + "devnull=" + os.DevNull, + ":=" + string(os.PathListSeparator), + } + + if runtime.GOOS == "plan9" { + ts.env = append(ts.env, "path="+testBin+string(filepath.ListSeparator)+os.Getenv("path")) + } + + if runtime.GOOS == "windows" { + ts.env = append(ts.env, "exe=.exe") + } else { + ts.env = append(ts.env, "exe=") + } + for _, key := range extraEnvKeys { + if val := os.Getenv(key); val != "" { + ts.env = append(ts.env, key+"="+val) + } + } + + ts.envMap = make(map[string]string) + for _, kv := range ts.env { + if i := strings.Index(kv, "="); i >= 0 { + ts.envMap[kv[:i]] = kv[i+1:] + } + } +} + +var execCache par.Cache + +// run runs the test script. +func (ts *testScript) run() { + // Truncate log at end of last phase marker, + // discarding details of successful phase. + rewind := func() { + if !testing.Verbose() { + ts.log.Truncate(ts.mark) + } + } + + // Insert elapsed time for phase at end of phase marker + markTime := func() { + if ts.mark > 0 && !ts.start.IsZero() { + afterMark := append([]byte{}, ts.log.Bytes()[ts.mark:]...) + ts.log.Truncate(ts.mark - 1) // cut \n and afterMark + fmt.Fprintf(&ts.log, " (%.3fs)\n", time.Since(ts.start).Seconds()) + ts.log.Write(afterMark) + } + ts.start = time.Time{} + } + + defer func() { + markTime() + // Flush testScript log to testing.T log. + ts.t.Log("\n" + ts.abbrev(ts.log.String())) + }() + + // Unpack archive. + a, err := txtar.ParseFile(ts.file) + ts.check(err) + for _, f := range a.Files { + name := ts.mkabs(ts.expand(f.Name)) + ts.check(os.MkdirAll(filepath.Dir(name), 0777)) + ts.check(ioutil.WriteFile(name, f.Data, 0666)) + } + + // With -v or -testwork, start log with full environment. + if *testWork || testing.Verbose() { + // Display environment. + ts.cmdEnv(false, nil) + fmt.Fprintf(&ts.log, "\n") + ts.mark = ts.log.Len() + } + + // Run script. + // See testdata/script/README for documentation of script form. + script := string(a.Comment) +Script: + for script != "" { + // Extract next line. + ts.lineno++ + var line string + if i := strings.Index(script, "\n"); i >= 0 { + line, script = script[:i], script[i+1:] + } else { + line, script = script, "" + } + + // # is a comment indicating the start of new phase. + if strings.HasPrefix(line, "#") { + // If there was a previous phase, it succeeded, + // so rewind the log to delete its details (unless -v is in use). + // If nothing has happened at all since the mark, + // rewinding is a no-op and adding elapsed time + // for doing nothing is meaningless, so don't. + if ts.log.Len() > ts.mark { + rewind() + markTime() + } + // Print phase heading and mark start of phase output. + fmt.Fprintf(&ts.log, "%s\n", line) + ts.mark = ts.log.Len() + ts.start = time.Now() + continue + } + + // Parse input line. Ignore blanks entirely. + args := ts.parse(line) + if len(args) == 0 { + continue + } + + // Echo command to log. + fmt.Fprintf(&ts.log, "> %s\n", line) + + // Command prefix [cond] means only run this command if cond is satisfied. + for strings.HasPrefix(args[0], "[") && strings.HasSuffix(args[0], "]") { + cond := args[0] + cond = cond[1 : len(cond)-1] + cond = strings.TrimSpace(cond) + args = args[1:] + if len(args) == 0 { + ts.fatalf("missing command after condition") + } + want := true + if strings.HasPrefix(cond, "!") { + want = false + cond = strings.TrimSpace(cond[1:]) + } + // Known conds are: $GOOS, $GOARCH, runtime.Compiler, and 'short' (for testing.Short). + // + // NOTE: If you make changes here, update testdata/script/README too! + // + ok := false + switch cond { + case runtime.GOOS, runtime.GOARCH, runtime.Compiler: + ok = true + case "short": + ok = testing.Short() + case "cgo": + ok = canCgo + case "msan": + ok = canMSan + case "race": + ok = canRace + case "net": + ok = testenv.HasExternalNetwork() + case "link": + ok = testenv.HasLink() + case "symlink": + ok = testenv.HasSymlink() + default: + if strings.HasPrefix(cond, "exec:") { + prog := cond[len("exec:"):] + ok = execCache.Do(prog, func() interface{} { + _, err := exec.LookPath(prog) + return err == nil + }).(bool) + break + } + if !imports.KnownArch[cond] && !imports.KnownOS[cond] && cond != "gc" && cond != "gccgo" { + ts.fatalf("unknown condition %q", cond) + } + } + if ok != want { + // Don't run rest of line. + continue Script + } + } + + // Command prefix ! means negate the expectations about this command: + // go command should fail, match should not be found, etc. + neg := false + if args[0] == "!" { + neg = true + args = args[1:] + if len(args) == 0 { + ts.fatalf("! on line by itself") + } + } + + // Run command. + cmd := scriptCmds[args[0]] + if cmd == nil { + ts.fatalf("unknown command %q", args[0]) + } + cmd(ts, neg, args[1:]) + + // Command can ask script to stop early. + if ts.stopped { + return + } + } + + // Final phase ended. + rewind() + markTime() + fmt.Fprintf(&ts.log, "PASS\n") +} + +// scriptCmds are the script command implementations. +// Keep list and the implementations below sorted by name. +// +// NOTE: If you make changes here, update testdata/script/README too! +// +var scriptCmds = map[string]func(*testScript, bool, []string){ + "addcrlf": (*testScript).cmdAddcrlf, + "cd": (*testScript).cmdCd, + "cmp": (*testScript).cmdCmp, + "cp": (*testScript).cmdCp, + "env": (*testScript).cmdEnv, + "exec": (*testScript).cmdExec, + "exists": (*testScript).cmdExists, + "go": (*testScript).cmdGo, + "grep": (*testScript).cmdGrep, + "mkdir": (*testScript).cmdMkdir, + "rm": (*testScript).cmdRm, + "skip": (*testScript).cmdSkip, + "stale": (*testScript).cmdStale, + "stderr": (*testScript).cmdStderr, + "stdout": (*testScript).cmdStdout, + "stop": (*testScript).cmdStop, + "symlink": (*testScript).cmdSymlink, +} + +// addcrlf adds CRLF line endings to the named files. +func (ts *testScript) cmdAddcrlf(neg bool, args []string) { + if len(args) == 0 { + ts.fatalf("usage: addcrlf file...") + } + + for _, file := range args { + file = ts.mkabs(file) + data, err := ioutil.ReadFile(file) + ts.check(err) + ts.check(ioutil.WriteFile(file, bytes.Replace(data, []byte("\n"), []byte("\r\n"), -1), 0666)) + } +} + +// cd changes to a different directory. +func (ts *testScript) cmdCd(neg bool, args []string) { + if neg { + ts.fatalf("unsupported: ! cd") + } + if len(args) != 1 { + ts.fatalf("usage: cd dir") + } + + dir := args[0] + if !filepath.IsAbs(dir) { + dir = filepath.Join(ts.cd, dir) + } + info, err := os.Stat(dir) + if os.IsNotExist(err) { + ts.fatalf("directory %s does not exist", dir) + } + ts.check(err) + if !info.IsDir() { + ts.fatalf("%s is not a directory", dir) + } + ts.cd = dir + fmt.Fprintf(&ts.log, "%s\n", ts.cd) +} + +// cmp compares two files. +func (ts *testScript) cmdCmp(neg bool, args []string) { + if neg { + // It would be strange to say "this file can have any content except this precise byte sequence". + ts.fatalf("unsupported: ! cmp") + } + if len(args) != 2 { + ts.fatalf("usage: cmp file1 file2") + } + + name1, name2 := args[0], args[1] + var text1, text2 string + if name1 == "stdout" { + text1 = ts.stdout + } else if name1 == "stderr" { + text1 = ts.stderr + } else { + data, err := ioutil.ReadFile(ts.mkabs(name1)) + ts.check(err) + text1 = string(data) + } + + data, err := ioutil.ReadFile(ts.mkabs(name2)) + ts.check(err) + text2 = string(data) + + if text1 == text2 { + return + } + + fmt.Fprintf(&ts.log, "[diff -%s +%s]\n%s\n", name1, name2, diff(text1, text2)) + ts.fatalf("%s and %s differ", name1, name2) +} + +// cp copies files, maybe eventually directories. +func (ts *testScript) cmdCp(neg bool, args []string) { + if neg { + ts.fatalf("unsupported: ! cp") + } + if len(args) < 2 { + ts.fatalf("usage: cp src... dst") + } + + dst := ts.mkabs(args[len(args)-1]) + info, err := os.Stat(dst) + dstDir := err == nil && info.IsDir() + if len(args) > 2 && !dstDir { + ts.fatalf("cp: destination %s is not a directory", dst) + } + + for _, arg := range args[:len(args)-1] { + src := ts.mkabs(arg) + info, err := os.Stat(src) + ts.check(err) + data, err := ioutil.ReadFile(src) + ts.check(err) + targ := dst + if dstDir { + targ = filepath.Join(dst, filepath.Base(src)) + } + ts.check(ioutil.WriteFile(targ, data, info.Mode()&0777)) + } +} + +// env displays or adds to the environment. +func (ts *testScript) cmdEnv(neg bool, args []string) { + if neg { + ts.fatalf("unsupported: ! env") + } + if len(args) == 0 { + printed := make(map[string]bool) // env list can have duplicates; only print effective value (from envMap) once + for _, kv := range ts.env { + k := kv[:strings.Index(kv, "=")] + if !printed[k] { + fmt.Fprintf(&ts.log, "%s=%s\n", k, ts.envMap[k]) + } + } + return + } + for _, env := range args { + i := strings.Index(env, "=") + if i < 0 { + // Display value instead of setting it. + fmt.Fprintf(&ts.log, "%s=%s\n", env, ts.envMap[env]) + continue + } + ts.env = append(ts.env, env) + ts.envMap[env[:i]] = env[i+1:] + } +} + +// exec runs the given command. +func (ts *testScript) cmdExec(neg bool, args []string) { + if len(args) < 1 { + ts.fatalf("usage: exec program [args...]") + } + var err error + ts.stdout, ts.stderr, err = ts.exec(args[0], args[1:]...) + if ts.stdout != "" { + fmt.Fprintf(&ts.log, "[stdout]\n%s", ts.stdout) + } + if ts.stderr != "" { + fmt.Fprintf(&ts.log, "[stderr]\n%s", ts.stderr) + } + if err != nil { + fmt.Fprintf(&ts.log, "[%v]\n", err) + if !neg { + ts.fatalf("unexpected command failure") + } + } else { + if neg { + ts.fatalf("unexpected command success") + } + } +} + +// exists checks that the list of files exists. +func (ts *testScript) cmdExists(neg bool, args []string) { + var readonly bool + if len(args) > 0 && args[0] == "-readonly" { + readonly = true + args = args[1:] + } + if len(args) == 0 { + ts.fatalf("usage: exists [-readonly] file...") + } + + for _, file := range args { + file = ts.mkabs(file) + info, err := os.Stat(file) + if err == nil && neg { + what := "file" + if info.IsDir() { + what = "directory" + } + ts.fatalf("%s %s unexpectedly exists", what, file) + } + if err != nil && !neg { + ts.fatalf("%s does not exist", file) + } + if err == nil && !neg && readonly && info.Mode()&0222 != 0 { + ts.fatalf("%s exists but is writable", file) + } + } +} + +// go runs the go command. +func (ts *testScript) cmdGo(neg bool, args []string) { + ts.cmdExec(neg, append([]string{testGo}, args...)) +} + +// mkdir creates directories. +func (ts *testScript) cmdMkdir(neg bool, args []string) { + if neg { + ts.fatalf("unsupported: ! mkdir") + } + if len(args) < 1 { + ts.fatalf("usage: mkdir dir...") + } + for _, arg := range args { + ts.check(os.MkdirAll(ts.mkabs(arg), 0777)) + } +} + +// rm removes files or directories. +func (ts *testScript) cmdRm(neg bool, args []string) { + if neg { + ts.fatalf("unsupported: ! rm") + } + if len(args) < 1 { + ts.fatalf("usage: rm file...") + } + for _, arg := range args { + file := ts.mkabs(arg) + removeAll(file) // does chmod and then attempts rm + ts.check(os.RemoveAll(file)) // report error + } +} + +// skip marks the test skipped. +func (ts *testScript) cmdSkip(neg bool, args []string) { + if len(args) > 1 { + ts.fatalf("usage: skip [msg]") + } + if neg { + ts.fatalf("unsupported: ! skip") + } + if len(args) == 1 { + ts.t.Skip(args[0]) + } + ts.t.Skip() +} + +// stale checks that the named build targets are stale. +func (ts *testScript) cmdStale(neg bool, args []string) { + if len(args) == 0 { + ts.fatalf("usage: stale target...") + } + tmpl := "{{if .Error}}{{.ImportPath}}: {{.Error.Err}}{else}}" + if neg { + tmpl += "{{if .Stale}}{{.ImportPath}} is unexpectedly stale{{end}}" + } else { + tmpl += "{{if not .Stale}}{{.ImportPath}} is unexpectedly NOT stale{{end}}" + } + tmpl += "{{end}}" + goArgs := append([]string{"list", "-e", "-f=" + tmpl}, args...) + stdout, stderr, err := ts.exec(testGo, goArgs...) + if err != nil { + ts.fatalf("go list: %v\n%s%s", err, stdout, stderr) + } + if stdout != "" { + ts.fatalf("%s", stdout) + } +} + +// stdout checks that the last go command standard output matches a regexp. +func (ts *testScript) cmdStdout(neg bool, args []string) { + scriptMatch(ts, neg, args, ts.stdout, "stdout") +} + +// stderr checks that the last go command standard output matches a regexp. +func (ts *testScript) cmdStderr(neg bool, args []string) { + scriptMatch(ts, neg, args, ts.stderr, "stderr") +} + +// grep checks that file content matches a regexp. +// Like stdout/stderr and unlike Unix grep, it accepts Go regexp syntax. +func (ts *testScript) cmdGrep(neg bool, args []string) { + scriptMatch(ts, neg, args, "", "grep") +} + +// scriptMatch implements both stdout and stderr. +func scriptMatch(ts *testScript, neg bool, args []string, text, name string) { + n := 0 + if len(args) >= 1 && strings.HasPrefix(args[0], "-count=") { + if neg { + ts.fatalf("cannot use -count= with negated match") + } + var err error + n, err = strconv.Atoi(args[0][len("-count="):]) + if err != nil { + ts.fatalf("bad -count=: %v", err) + } + if n < 1 { + ts.fatalf("bad -count=: must be at least 1") + } + args = args[1:] + } + + extraUsage := "" + want := 1 + if name == "grep" { + extraUsage = " file" + want = 2 + } + if len(args) != want { + ts.fatalf("usage: %s [-count=N] 'pattern' file%s", name, extraUsage) + } + + pattern := args[0] + re, err := regexp.Compile(`(?m)` + pattern) + ts.check(err) + + isGrep := name == "grep" + if isGrep { + name = args[1] // for error messages + data, err := ioutil.ReadFile(ts.mkabs(args[1])) + ts.check(err) + text = string(data) + } + + if neg { + if re.MatchString(text) { + if isGrep { + fmt.Fprintf(&ts.log, "[%s]\n%s\n", name, text) + } + ts.fatalf("unexpected match for %#q found in %s: %s", pattern, name, re.FindString(text)) + } + } else { + if !re.MatchString(text) { + if isGrep { + fmt.Fprintf(&ts.log, "[%s]\n%s\n", name, text) + } + ts.fatalf("no match for %#q found in %s", pattern, name) + } + if n > 0 { + count := len(re.FindAllString(text, -1)) + if count != n { + if isGrep { + fmt.Fprintf(&ts.log, "[%s]\n%s\n", name, text) + } + ts.fatalf("have %d matches for %#q, want %d", count, pattern, n) + } + } + } +} + +// stop stops execution of the test (marking it passed). +func (ts *testScript) cmdStop(neg bool, args []string) { + if neg { + ts.fatalf("unsupported: ! stop") + } + if len(args) > 1 { + ts.fatalf("usage: stop [msg]") + } + if len(args) == 1 { + fmt.Fprintf(&ts.log, "stop: %s\n", args[0]) + } else { + fmt.Fprintf(&ts.log, "stop\n") + } + ts.stopped = true +} + +// symlink creates a symbolic link. +func (ts *testScript) cmdSymlink(neg bool, args []string) { + if neg { + ts.fatalf("unsupported: ! symlink") + } + if len(args) != 3 || args[1] != "->" { + ts.fatalf("usage: symlink file -> target") + } + // Note that the link target args[2] is not interpreted with mkabs: + // it will be interpreted relative to the directory file is in. + ts.check(os.Symlink(args[2], ts.mkabs(args[0]))) +} + +// Helpers for command implementations. + +// abbrev abbreviates the actual work directory in the string s to the literal string "$WORK". +func (ts *testScript) abbrev(s string) string { + s = strings.Replace(s, ts.workdir, "$WORK", -1) + if *testWork { + // Expose actual $WORK value in environment dump on first line of work script, + // so that the user can find out what directory -testwork left behind. + s = "WORK=" + ts.workdir + "\n" + strings.TrimPrefix(s, "WORK=$WORK\n") + } + return s +} + +// check calls ts.fatalf if err != nil. +func (ts *testScript) check(err error) { + if err != nil { + ts.fatalf("%v", err) + } +} + +// exec runs the given command line (an actual subprocess, not simulated) +// in ts.cd with environment ts.env and then returns collected standard output and standard error. +func (ts *testScript) exec(command string, args ...string) (stdout, stderr string, err error) { + cmd := exec.Command(command, args...) + cmd.Dir = ts.cd + cmd.Env = append(ts.env, "PWD="+ts.cd) + var stdoutBuf, stderrBuf strings.Builder + cmd.Stdout = &stdoutBuf + cmd.Stderr = &stderrBuf + err = cmd.Run() + return stdoutBuf.String(), stderrBuf.String(), err +} + +// expand applies environment variable expansion to the string s. +func (ts *testScript) expand(s string) string { + return os.Expand(s, func(key string) string { return ts.envMap[key] }) +} + +// fatalf aborts the test with the given failure message. +func (ts *testScript) fatalf(format string, args ...interface{}) { + fmt.Fprintf(&ts.log, "FAIL: %s:%d: %s\n", ts.file, ts.lineno, fmt.Sprintf(format, args...)) + ts.t.FailNow() +} + +// mkabs interprets file relative to the test script's current directory +// and returns the corresponding absolute path. +func (ts *testScript) mkabs(file string) string { + if filepath.IsAbs(file) { + return file + } + return filepath.Join(ts.cd, file) +} + +// parse parses a single line as a list of space-separated arguments +// subject to environment variable expansion (but not resplitting). +// Single quotes around text disable splitting and expansion. +// To embed a single quote, double it: 'Don''t communicate by sharing memory.' +func (ts *testScript) parse(line string) []string { + ts.line = line + + var ( + args []string + arg string // text of current arg so far (need to add line[start:i]) + start = -1 // if >= 0, position where current arg text chunk starts + quoted = false // currently processing quoted text + ) + for i := 0; ; i++ { + if !quoted && (i >= len(line) || line[i] == ' ' || line[i] == '\t' || line[i] == '\r' || line[i] == '#') { + // Found arg-separating space. + if start >= 0 { + arg += ts.expand(line[start:i]) + args = append(args, arg) + start = -1 + arg = "" + } + if i >= len(line) || line[i] == '#' { + break + } + continue + } + if i >= len(line) { + ts.fatalf("unterminated quoted argument") + } + if line[i] == '\'' { + if !quoted { + // starting a quoted chunk + if start >= 0 { + arg += ts.expand(line[start:i]) + } + start = i + 1 + quoted = true + continue + } + // 'foo''bar' means foo'bar, like in rc shell and Pascal. + if i+1 < len(line) && line[i+1] == '\'' { + arg += line[start:i] + start = i + 1 + i++ // skip over second ' before next iteration + continue + } + // ending a quoted chunk + arg += line[start:i] + start = i + 1 + quoted = false + continue + } + // found character worth saving; make sure we're saving + if start < 0 { + start = i + } + } + return args +} + +// diff returns a formatted diff of the two texts, +// showing the entire text and the minimum line-level +// additions and removals to turn text1 into text2. +// (That is, lines only in text1 appear with a leading -, +// and lines only in text2 appear with a leading +.) +func diff(text1, text2 string) string { + if text1 != "" && !strings.HasSuffix(text1, "\n") { + text1 += "(missing final newline)" + } + lines1 := strings.Split(text1, "\n") + lines1 = lines1[:len(lines1)-1] // remove empty string after final line + if text2 != "" && !strings.HasSuffix(text2, "\n") { + text2 += "(missing final newline)" + } + lines2 := strings.Split(text2, "\n") + lines2 = lines2[:len(lines2)-1] // remove empty string after final line + + // Naive dynamic programming algorithm for edit distance. + // https://en.wikipedia.org/wiki/Wagner–Fischer_algorithm + // dist[i][j] = edit distance between lines1[:len(lines1)-i] and lines2[:len(lines2)-j] + // (The reversed indices make following the minimum cost path + // visit lines in the same order as in the text.) + dist := make([][]int, len(lines1)+1) + for i := range dist { + dist[i] = make([]int, len(lines2)+1) + if i == 0 { + for j := range dist[0] { + dist[0][j] = j + } + continue + } + for j := range dist[i] { + if j == 0 { + dist[i][0] = i + continue + } + cost := dist[i][j-1] + 1 + if cost > dist[i-1][j]+1 { + cost = dist[i-1][j] + 1 + } + if lines1[len(lines1)-i] == lines2[len(lines2)-j] { + if cost > dist[i-1][j-1] { + cost = dist[i-1][j-1] + } + } + dist[i][j] = cost + } + } + + var buf strings.Builder + i, j := len(lines1), len(lines2) + for i > 0 || j > 0 { + cost := dist[i][j] + if i > 0 && j > 0 && cost == dist[i-1][j-1] && lines1[len(lines1)-i] == lines2[len(lines2)-j] { + fmt.Fprintf(&buf, " %s\n", lines1[len(lines1)-i]) + i-- + j-- + } else if i > 0 && cost == dist[i-1][j]+1 { + fmt.Fprintf(&buf, "-%s\n", lines1[len(lines1)-i]) + i-- + } else { + fmt.Fprintf(&buf, "+%s\n", lines2[len(lines2)-j]) + j-- + } + } + return buf.String() +} + +var diffTests = []struct { + text1 string + text2 string + diff string +}{ + {"a b c", "a b d e f", "a b -c +d +e +f"}, + {"", "a b c", "+a +b +c"}, + {"a b c", "", "-a -b -c"}, + {"a b c", "d e f", "-a -b -c +d +e +f"}, + {"a b c d e f", "a b d e f", "a b -c d e f"}, + {"a b c e f", "a b c d e f", "a b c +d e f"}, +} + +func TestDiff(t *testing.T) { + for _, tt := range diffTests { + // Turn spaces into \n. + text1 := strings.Replace(tt.text1, " ", "\n", -1) + if text1 != "" { + text1 += "\n" + } + text2 := strings.Replace(tt.text2, " ", "\n", -1) + if text2 != "" { + text2 += "\n" + } + out := diff(text1, text2) + // Cut final \n, cut spaces, turn remaining \n into spaces. + out = strings.Replace(strings.Replace(strings.TrimSuffix(out, "\n"), " ", "", -1), "\n", " ", -1) + if out != tt.diff { + t.Errorf("diff(%q, %q) = %q, want %q", text1, text2, out, tt.diff) + } + } +} diff --git a/libgo/go/cmd/go/testdata/addmod.go b/libgo/go/cmd/go/testdata/addmod.go new file mode 100644 index 00000000000..19850af0f37 --- /dev/null +++ b/libgo/go/cmd/go/testdata/addmod.go @@ -0,0 +1,154 @@ +// 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 + +// Addmod adds a module as a txtar archive to the testdata/mod directory. +// +// Usage: +// +// go run addmod.go path@version... +// +// It should only be used for very small modules - we do not want to check +// very large files into testdata/mod. +// +// It is acceptable to edit the archive afterward to remove or shorten files. +// See mod/README for more information. +// +package main + +import ( + "bytes" + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "os/exec" + "path/filepath" + "strings" + + "../internal/txtar" +) + +func usage() { + fmt.Fprintf(os.Stderr, "usage: go run addmod.go path@version...\n") + os.Exit(2) +} + +var tmpdir string + +func fatalf(format string, args ...interface{}) { + os.RemoveAll(tmpdir) + log.Fatalf(format, args...) +} + +const goCmd = "vgo" + +func main() { + flag.Usage = usage + flag.Parse() + if flag.NArg() == 0 { + usage() + } + + log.SetPrefix("addmod: ") + log.SetFlags(0) + + var err error + tmpdir, err = ioutil.TempDir("", "addmod-") + if err != nil { + log.Fatal(err) + } + + run := func(command string, args ...string) string { + cmd := exec.Command(command, args...) + cmd.Dir = tmpdir + var stderr bytes.Buffer + cmd.Stderr = &stderr + out, err := cmd.Output() + if err != nil { + fatalf("%s %s: %v\n%s", command, strings.Join(args, " "), err, stderr.Bytes()) + } + return string(out) + } + + gopath := strings.TrimSpace(run("go", "env", "GOPATH")) + if gopath == "" { + fatalf("cannot find GOPATH") + } + + exitCode := 0 + for _, arg := range flag.Args() { + if err := ioutil.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte("module m\n"), 0666); err != nil { + fatalf("%v", err) + } + run(goCmd, "get", "-d", arg) + path := arg + if i := strings.Index(path, "@"); i >= 0 { + path = path[:i] + } + out := run(goCmd, "list", "-m", "-f={{.Path}} {{.Version}} {{.Dir}}", path) + f := strings.Fields(out) + if len(f) != 3 { + log.Printf("go list -m %s: unexpected output %q", arg, out) + exitCode = 1 + continue + } + path, vers, dir := f[0], f[1], f[2] + mod, err := ioutil.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".mod")) + if err != nil { + log.Printf("%s: %v", arg, err) + exitCode = 1 + continue + } + info, err := ioutil.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".info")) + if err != nil { + log.Printf("%s: %v", arg, err) + exitCode = 1 + continue + } + + a := new(txtar.Archive) + title := arg + if !strings.Contains(arg, "@") { + title += "@" + vers + } + a.Comment = []byte(fmt.Sprintf("module %s\n\n", title)) + a.Files = []txtar.File{ + {Name: ".mod", Data: mod}, + {Name: ".info", Data: info}, + } + dir = filepath.Clean(dir) + err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if !info.Mode().IsRegular() { + return nil + } + name := info.Name() + if name == "go.mod" || strings.HasSuffix(name, ".go") { + data, err := ioutil.ReadFile(path) + if err != nil { + return err + } + a.Files = append(a.Files, txtar.File{Name: strings.TrimPrefix(path, dir+string(filepath.Separator)), Data: data}) + } + return nil + }) + if err != nil { + log.Printf("%s: %v", arg, err) + exitCode = 1 + continue + } + + data := txtar.Format(a) + target := filepath.Join("mod", strings.Replace(path, "/", "_", -1)+"_"+vers+".txt") + if err := ioutil.WriteFile(target, data, 0666); err != nil { + log.Printf("%s: %v", arg, err) + exitCode = 1 + continue + } + } + os.RemoveAll(tmpdir) + os.Exit(exitCode) +} diff --git a/libgo/go/cmd/go/testdata/badmod/go.mod b/libgo/go/cmd/go/testdata/badmod/go.mod new file mode 100644 index 00000000000..f7f64238700 --- /dev/null +++ b/libgo/go/cmd/go/testdata/badmod/go.mod @@ -0,0 +1 @@ +module m diff --git a/libgo/go/cmd/go/testdata/badmod/x.go b/libgo/go/cmd/go/testdata/badmod/x.go new file mode 100644 index 00000000000..579fb086eeb --- /dev/null +++ b/libgo/go/cmd/go/testdata/badmod/x.go @@ -0,0 +1,4 @@ +package x + +import _ "appengine" +import _ "nonexistent.rsc.io" // domain does not exist diff --git a/libgo/go/cmd/go/testdata/importcycle/src/selfimport/selfimport.go b/libgo/go/cmd/go/testdata/importcycle/src/selfimport/selfimport.go new file mode 100644 index 00000000000..dc63c4b9f29 --- /dev/null +++ b/libgo/go/cmd/go/testdata/importcycle/src/selfimport/selfimport.go @@ -0,0 +1,3 @@ +package selfimport + +import "selfimport" diff --git a/libgo/go/cmd/go/testdata/mod/README b/libgo/go/cmd/go/testdata/mod/README new file mode 100644 index 00000000000..43ddf77eff3 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/README @@ -0,0 +1,36 @@ +This directory holds Go modules served by a Go module proxy +that runs on localhost during tests, both to make tests avoid +requiring specific network servers and also to make them +significantly faster. + +A small go get'able test module can be added here by running + + cd cmd/go/testdata + go run addmod.go path@vers + +where path and vers are the module path and version to add here. + +For interactive experimentation using this set of modules, run: + + cd cmd/go + go test -proxy=localhost:1234 & + export GOPROXY=http://localhost:1234/mod + +and then run go commands as usual. + +Modules saved to this directory should be small: a few kilobytes at most. +It is acceptable to edit the archives created by addmod.go to remove +or shorten files. It is also acceptable to write module archives by hand: +they need not be backed by some public git repo. + +Each module archive is named path_vers.txt, where slashes in path +have been replaced with underscores. The archive must contain +two files ".info" and ".mod", to be served as the info and mod files +in the proxy protocol (see https://research.swtch.com/vgo-module). +The remaining files are served as the content of the module zip file. +The path@vers prefix required of files in the zip file is added +automatically by the proxy: the files in the archive have names without +the prefix, like plain "go.mod", "x.go", and so on. + +See ../addmod.go and ../savedir.go for tools to generate txtar files, +although again it is also fine to write them by hand. diff --git a/libgo/go/cmd/go/testdata/mod/example.com_join_subpkg_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_join_subpkg_v1.0.0.txt new file mode 100644 index 00000000000..1ecfa0b6de9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_join_subpkg_v1.0.0.txt @@ -0,0 +1,9 @@ +Written by hand. +Test case for package moved into a parent module. + +-- .mod -- +module example.com/join/subpkg +-- .info -- +{"Version": "v1.0.0"} +-- x.go -- +package subpkg diff --git a/libgo/go/cmd/go/testdata/mod/example.com_join_subpkg_v1.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_join_subpkg_v1.1.0.txt new file mode 100644 index 00000000000..9eb823adb76 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_join_subpkg_v1.1.0.txt @@ -0,0 +1,9 @@ +Written by hand. +Test case for package moved into a parent module. + +-- .mod -- +module example.com/join/subpkg + +require example.com/join v1.1.0 +-- .info -- +{"Version": "v1.1.0"} diff --git a/libgo/go/cmd/go/testdata/mod/example.com_join_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_join_v1.0.0.txt new file mode 100644 index 00000000000..84c68b13b6d --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_join_v1.0.0.txt @@ -0,0 +1,7 @@ +Written by hand. +Test case for package moved into a parent module. + +-- .mod -- +module example.com/join +-- .info -- +{"Version": "v1.0.0"} diff --git a/libgo/go/cmd/go/testdata/mod/example.com_join_v1.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_join_v1.1.0.txt new file mode 100644 index 00000000000..5f92036d9e7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_join_v1.1.0.txt @@ -0,0 +1,9 @@ +Written by hand. +Test case for package moved into a parent module. + +-- .mod -- +module example.com/join +-- .info -- +{"Version": "v1.1.0"} +-- subpkg/x.go -- +package subpkg diff --git a/libgo/go/cmd/go/testdata/mod/example.com_split_subpkg_v1.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_split_subpkg_v1.1.0.txt new file mode 100644 index 00000000000..b197b663981 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_split_subpkg_v1.1.0.txt @@ -0,0 +1,11 @@ +Written by hand. +Test case for getting a package that has been moved to a different module. + +-- .mod -- +module example.com/split/subpkg + +require example.com/split v1.1.0 +-- .info -- +{"Version": "v1.1.0"} +-- x.go -- +package subpkg diff --git a/libgo/go/cmd/go/testdata/mod/example.com_split_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_split_v1.0.0.txt new file mode 100644 index 00000000000..b706e590d98 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_split_v1.0.0.txt @@ -0,0 +1,9 @@ +Written by hand. +Test case for getting a package that has been moved to a different module. + +-- .mod -- +module example.com/split +-- .info -- +{"Version": "v1.0.0"} +-- subpkg/x.go -- +package subpkg diff --git a/libgo/go/cmd/go/testdata/mod/example.com_split_v1.1.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_split_v1.1.0.txt new file mode 100644 index 00000000000..d38971f9b62 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_split_v1.1.0.txt @@ -0,0 +1,9 @@ +Written by hand. +Test case for getting a package that has been moved to a different module. + +-- .mod -- +module example.com/split + +require example.com/split/subpkg v1.1.0 +-- .info -- +{"Version": "v1.1.0"} diff --git a/libgo/go/cmd/go/testdata/mod/example.com_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/example.com_v1.0.0.txt new file mode 100644 index 00000000000..263287d9e2c --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/example.com_v1.0.0.txt @@ -0,0 +1,9 @@ +Written by hand. +Test case for module at root of domain. + +-- .mod -- +module example.com +-- .info -- +{"Version": "v1.0.0"} +-- x.go -- +package x diff --git a/libgo/go/cmd/go/testdata/mod/golang.org_notx_useinternal_v0.1.0.txt b/libgo/go/cmd/go/testdata/mod/golang.org_notx_useinternal_v0.1.0.txt new file mode 100644 index 00000000000..0420a1a4a0a --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/golang.org_notx_useinternal_v0.1.0.txt @@ -0,0 +1,13 @@ +written by hand — attempts to use a prohibited internal package +(https://golang.org/s/go14internal) + +-- .mod -- +module golang.org/notx/useinternal +-- .info -- +{"Version":"v0.1.0","Name":"","Short":"","Time":"2018-07-25T17:24:00Z"} +-- go.mod -- +module golang.org/notx/useinternal +-- useinternal.go -- +package useinternal + +import _ "golang.org/x/internal/subtle" diff --git a/libgo/go/cmd/go/testdata/mod/golang.org_x_internal_v0.1.0.txt b/libgo/go/cmd/go/testdata/mod/golang.org_x_internal_v0.1.0.txt new file mode 100644 index 00000000000..5737e95cf47 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/golang.org_x_internal_v0.1.0.txt @@ -0,0 +1,43 @@ +written by hand — loosely derived from golang.org/x/crypto/internal/subtle, +but splitting the internal package across a module boundary + +-- .mod -- +module golang.org/x/internal +-- .info -- +{"Version":"v0.1.0","Name":"","Short":"","Time":"2018-07-25T17:24:00Z"} +-- go.mod -- +module golang.org/x/internal +-- subtle/aliasing.go -- +// 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 !appengine + +// This is a tiny version of golang.org/x/crypto/internal/subtle. + +package subtle + +import "unsafe" + +func AnyOverlap(x, y []byte) bool { + return len(x) > 0 && len(y) > 0 && + uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && + uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) +} +-- subtle/aliasing_appengine.go -- +// 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 appengine + +package subtle + +import "reflect" + +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() +} diff --git a/libgo/go/cmd/go/testdata/mod/golang.org_x_text_v0.0.0-20170915032832-14c0d48ead0c.txt b/libgo/go/cmd/go/testdata/mod/golang.org_x_text_v0.0.0-20170915032832-14c0d48ead0c.txt new file mode 100644 index 00000000000..f4f50cdedb6 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/golang.org_x_text_v0.0.0-20170915032832-14c0d48ead0c.txt @@ -0,0 +1,47 @@ +written by hand - just enough to compile rsc.io/sampler, rsc.io/quote + +-- .mod -- +module golang.org/x/text +-- .info -- +{"Version":"v0.0.0-20170915032832-14c0d48ead0c","Name":"v0.0.0-20170915032832-14c0d48ead0c","Short":"14c0d48ead0c","Time":"2017-09-15T03:28:32Z"} +-- go.mod -- +module golang.org/x/text +-- unused/unused.go -- +package unused +-- language/lang.go -- +// 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 is a tiny version of golang.org/x/text. + +package language + +import "strings" + +type Tag string + +func Make(s string) Tag { return Tag(s) } + +func (t Tag) String() string { return string(t) } + +func NewMatcher(tags []Tag) Matcher { return &matcher{tags} } + +type Matcher interface { + Match(...Tag) (Tag, int, int) +} + +type matcher struct { + tags []Tag +} + +func (m *matcher) Match(prefs ...Tag) (Tag, int, int) { + for _, pref := range prefs { + for _, tag := range m.tags { + if tag == pref || strings.HasPrefix(string(pref), string(tag+"-")) || strings.HasPrefix(string(tag), string(pref+"-")) { + return tag, 0, 0 + } + } + } + return m.tags[0], 0, 0 +} diff --git a/libgo/go/cmd/go/testdata/mod/golang.org_x_text_v0.3.0.txt b/libgo/go/cmd/go/testdata/mod/golang.org_x_text_v0.3.0.txt new file mode 100644 index 00000000000..5561afae8ed --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/golang.org_x_text_v0.3.0.txt @@ -0,0 +1,47 @@ +written by hand - just enough to compile rsc.io/sampler, rsc.io/quote + +-- .mod -- +module golang.org/x/text +-- .info -- +{"Version":"v0.3.0","Name":"","Short":"","Time":"2017-09-16T03:28:32Z"} +-- go.mod -- +module golang.org/x/text +-- unused/unused.go -- +package unused +-- language/lang.go -- +// 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 is a tiny version of golang.org/x/text. + +package language + +import "strings" + +type Tag string + +func Make(s string) Tag { return Tag(s) } + +func (t Tag) String() string { return string(t) } + +func NewMatcher(tags []Tag) Matcher { return &matcher{tags} } + +type Matcher interface { + Match(...Tag) (Tag, int, int) +} + +type matcher struct { + tags []Tag +} + +func (m *matcher) Match(prefs ...Tag) (Tag, int, int) { + for _, pref := range prefs { + for _, tag := range m.tags { + if tag == pref || strings.HasPrefix(string(pref), string(tag+"-")) || strings.HasPrefix(string(tag), string(pref+"-")) { + return tag, 0, 0 + } + } + } + return m.tags[0], 0, 0 +} diff --git a/libgo/go/cmd/go/testdata/mod/golang.org_x_useinternal_v0.1.0.txt b/libgo/go/cmd/go/testdata/mod/golang.org_x_useinternal_v0.1.0.txt new file mode 100644 index 00000000000..3fcba447bef --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/golang.org_x_useinternal_v0.1.0.txt @@ -0,0 +1,13 @@ +written by hand — uses an internal package from another module +(https://golang.org/s/go14internal) + +-- .mod -- +module golang.org/x/useinternal +-- .info -- +{"Version":"v0.1.0","Name":"","Short":"","Time":"2018-07-25T17:24:00Z"} +-- go.mod -- +module golang.org/x/useinternal +-- useinternal.go -- +package useinternal + +import _ "golang.org/x/internal/subtle" diff --git a/libgo/go/cmd/go/testdata/mod/gopkg.in_dummy.v2-unstable_v2.0.0.txt b/libgo/go/cmd/go/testdata/mod/gopkg.in_dummy.v2-unstable_v2.0.0.txt new file mode 100644 index 00000000000..f174159fd3f --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/gopkg.in_dummy.v2-unstable_v2.0.0.txt @@ -0,0 +1,9 @@ +gopkg.in/dummy.v2-unstable v2.0.0 +written by hand + +-- .mod -- +module gopkg.in/dummy.v2-unstable +-- .info -- +{"Version":"v2.0.0"} +-- dummy.go -- +package dummy diff --git a/libgo/go/cmd/go/testdata/mod/research.swtch.com_vgo-tour_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/research.swtch.com_vgo-tour_v1.0.0.txt new file mode 100644 index 00000000000..0f060dc8e32 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/research.swtch.com_vgo-tour_v1.0.0.txt @@ -0,0 +1,23 @@ +research.swtch.com/vgo-tour@v1.0.0 + +-- .mod -- +module "research.swtch.com/vgo-tour" +-- .info -- +{"Version":"v1.0.0","Name":"84de74b35823c1e49634f2262f1a58cfc951ebae","Short":"84de74b35823","Time":"2018-02-20T00:04:00Z"} +-- go.mod -- +module "research.swtch.com/vgo-tour" +-- hello.go -- +// 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 ( + "fmt" + "rsc.io/quote" +) + +func main() { + fmt.Println(quote.Hello()) +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_!c!g!o_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_!c!g!o_v1.0.0.txt new file mode 100644 index 00000000000..6276147535b --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_!c!g!o_v1.0.0.txt @@ -0,0 +1,19 @@ +rsc.io/CGO v1.0.0 + +-- .mod -- +module rsc.io/CGO +-- .info -- +{"Version":"v1.0.0","Name":"","Short":"","Time":"2018-08-01T18:23:45Z"} +-- go.mod -- +module rsc.io/CGO +-- cgo.go -- +// 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 CGO + +// #cgo CFLAGS: -I${SRCDIR} +import "C" + +var V = 0 diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_!q!u!o!t!e_v1.5.2.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_!q!u!o!t!e_v1.5.2.txt new file mode 100644 index 00000000000..21185c39f33 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_!q!u!o!t!e_v1.5.2.txt @@ -0,0 +1,88 @@ +rsc.io/QUOTE v1.5.2 + +-- .mod -- +module rsc.io/QUOTE + +require rsc.io/quote v1.5.2 +-- .info -- +{"Version":"v1.5.2","Name":"","Short":"","Time":"2018-07-15T16:25:34Z"} +-- go.mod -- +module rsc.io/QUOTE + +require rsc.io/quote v1.5.2 +-- QUOTE/quote.go -- +// 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 QUOTE COLLECTS LOUD SAYINGS. +package QUOTE + +import ( + "strings" + + "rsc.io/quote" +) + +// HELLO RETURNS A GREETING. +func HELLO() string { + return strings.ToUpper(quote.Hello()) +} + +// GLASS RETURNS A USEFUL PHRASE FOR WORLD TRAVELERS. +func GLASS() string { + return strings.ToUpper(quote.GLASS()) +} + +// GO RETURNS A GO PROVERB. +func GO() string { + return strings.ToUpper(quote.GO()) +} + +// OPT RETURNS AN OPTIMIZATION TRUTH. +func OPT() string { + return strings.ToUpper(quote.OPT()) +} +-- QUOTE/quote_test.go -- +// 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 QUOTE + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHELLO(t *testing.T) { + hello := "HELLO, WORLD" + if out := HELLO(); out != hello { + t.Errorf("HELLO() = %q, want %q", out, hello) + } +} + +func TestGLASS(t *testing.T) { + glass := "I CAN EAT GLASS AND IT DOESN'T HURT ME." + if out := GLASS(); out != glass { + t.Errorf("GLASS() = %q, want %q", out, glass) + } +} + +func TestGO(t *testing.T) { + go1 := "DON'T COMMUNICATE BY SHARING MEMORY, SHARE MEMORY BY COMMUNICATING." + if out := GO(); out != go1 { + t.Errorf("GO() = %q, want %q", out, go1) + } +} + +func TestOPT(t *testing.T) { + opt := "IF A PROGRAM IS TOO SLOW, IT MUST HAVE A LOOP." + if out := OPT(); out != opt { + t.Errorf("OPT() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_!q!u!o!t!e_v1.5.3-!p!r!e.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_!q!u!o!t!e_v1.5.3-!p!r!e.txt new file mode 100644 index 00000000000..54bac2df7bb --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_!q!u!o!t!e_v1.5.3-!p!r!e.txt @@ -0,0 +1,88 @@ +rsc.io/QUOTE v1.5.3-PRE (sigh) + +-- .mod -- +module rsc.io/QUOTE + +require rsc.io/quote v1.5.2 +-- .info -- +{"Version":"v1.5.3-PRE","Name":"","Short":"","Time":"2018-07-15T16:25:34Z"} +-- go.mod -- +module rsc.io/QUOTE + +require rsc.io/quote v1.5.2 +-- QUOTE/quote.go -- +// 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 QUOTE COLLECTS LOUD SAYINGS. +package QUOTE + +import ( + "strings" + + "rsc.io/quote" +) + +// HELLO RETURNS A GREETING. +func HELLO() string { + return strings.ToUpper(quote.Hello()) +} + +// GLASS RETURNS A USEFUL PHRASE FOR WORLD TRAVELERS. +func GLASS() string { + return strings.ToUpper(quote.GLASS()) +} + +// GO RETURNS A GO PROVERB. +func GO() string { + return strings.ToUpper(quote.GO()) +} + +// OPT RETURNS AN OPTIMIZATION TRUTH. +func OPT() string { + return strings.ToUpper(quote.OPT()) +} +-- QUOTE/quote_test.go -- +// 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 QUOTE + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHELLO(t *testing.T) { + hello := "HELLO, WORLD" + if out := HELLO(); out != hello { + t.Errorf("HELLO() = %q, want %q", out, hello) + } +} + +func TestGLASS(t *testing.T) { + glass := "I CAN EAT GLASS AND IT DOESN'T HURT ME." + if out := GLASS(); out != glass { + t.Errorf("GLASS() = %q, want %q", out, glass) + } +} + +func TestGO(t *testing.T) { + go1 := "DON'T COMMUNICATE BY SHARING MEMORY, SHARE MEMORY BY COMMUNICATING." + if out := GO(); out != go1 { + t.Errorf("GO() = %q, want %q", out, go1) + } +} + +func TestOPT(t *testing.T) { + opt := "IF A PROGRAM IS TOO SLOW, IT MUST HAVE A LOOP." + if out := OPT(); out != opt { + t.Errorf("OPT() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_badfile1_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_badfile1_v1.0.0.txt new file mode 100644 index 00000000000..9d23e7db98c --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_badfile1_v1.0.0.txt @@ -0,0 +1,14 @@ +rsc.io/badfile1 v1.0.0 +written by hand +this is part of the badfile test but is a valid zip file. + +-- .mod -- +module rsc.io/badfile1 +-- .info -- +{"Version":"v1.0.0"} +-- go.mod -- +module rsc.io/badfile1 +-- α.go -- +package α +-- .gitignore -- +-- x/y/z/.gitignore -- diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_badfile2_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_badfile2_v1.0.0.txt new file mode 100644 index 00000000000..58e1e1c103a --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_badfile2_v1.0.0.txt @@ -0,0 +1,12 @@ +rsc.io/badfile1 v1.0.0 +written by hand + +-- .mod -- +module rsc.io/badfile2 +-- .info -- +{"Version":"v1.0.0"} +-- go.mod -- +module rsc.io/badfile2 +-- ☺.go -- +package smiley + diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_badfile3_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_badfile3_v1.0.0.txt new file mode 100644 index 00000000000..a008448c5fd --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_badfile3_v1.0.0.txt @@ -0,0 +1,12 @@ +rsc.io/badfile3 v1.0.0 +written by hand + +-- .mod -- +module rsc.io/badfile3 +-- .info -- +{"Version":"v1.0.0"} +-- go.mod -- +module rsc.io/badfile3 +-- x?y.go -- +package x + diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_badfile4_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_badfile4_v1.0.0.txt new file mode 100644 index 00000000000..e28844dc632 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_badfile4_v1.0.0.txt @@ -0,0 +1,15 @@ +rsc.io/badfile4 v1.0.0 +written by hand + +-- .mod -- +module rsc.io/badfile4 +-- .info -- +{"Version":"v1.0.0"} +-- go.mod -- +module rsc.io/badfile4 +-- x/Y.go -- +package x +-- x/y.go -- +package x + + diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_badfile5_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_badfile5_v1.0.0.txt new file mode 100644 index 00000000000..3c7903a3bc0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_badfile5_v1.0.0.txt @@ -0,0 +1,13 @@ +rsc.io/badfile5 v1.0.0 +written by hand + +-- .mod -- +module rsc.io/badfile5 +-- .info -- +{"Version":"v1.0.0"} +-- go.mod -- +module rsc.io/badfile5 +-- x/y/z/w.go -- +package z +-- x/Y/zz/ww.go -- +package zz diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_badmod_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_badmod_v1.0.0.txt new file mode 100644 index 00000000000..993ceb7a0be --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_badmod_v1.0.0.txt @@ -0,0 +1,11 @@ +rsc.io/badmod v1.0.0 +written by hand + +-- .mod -- +module rsc.io/badmod +hello world +-- .info -- +{"Version":"v1.0.0"} +-- x.go -- +package x + diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_breaker_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_breaker_v1.0.0.txt new file mode 100644 index 00000000000..a103e3f8aa1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_breaker_v1.0.0.txt @@ -0,0 +1,11 @@ +rsc.io/breaker v1.0.0 +written by hand + +-- .mod -- +module rsc.io/breaker +-- .info -- +{"Version":"v1.0.0"} +-- breaker.go -- +package breaker + +const X = 1 diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_breaker_v2.0.0+incompatible.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_breaker_v2.0.0+incompatible.txt new file mode 100644 index 00000000000..59d8bacf078 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_breaker_v2.0.0+incompatible.txt @@ -0,0 +1,11 @@ +rsc.io/breaker v2.0.0+incompatible +written by hand + +-- .mod -- +module rsc.io/breaker +-- .info -- +{"Version":"v2.0.0+incompatible", "Name": "7307b307f4f0dde421900f8e5126fadac1e13aed", "Short": "7307b307f4f0"} +-- breaker.go -- +package breaker + +const XX = 2 diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_breaker_v2.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_breaker_v2.0.0.txt new file mode 100644 index 00000000000..59d8bacf078 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_breaker_v2.0.0.txt @@ -0,0 +1,11 @@ +rsc.io/breaker v2.0.0+incompatible +written by hand + +-- .mod -- +module rsc.io/breaker +-- .info -- +{"Version":"v2.0.0+incompatible", "Name": "7307b307f4f0dde421900f8e5126fadac1e13aed", "Short": "7307b307f4f0"} +-- breaker.go -- +package breaker + +const XX = 2 diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v1.0.0.txt new file mode 100644 index 00000000000..d8a71f3cd93 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v1.0.0.txt @@ -0,0 +1,15 @@ +rsc.io/fortune v1.0.0 +written by hand + +-- .mod -- +module rsc.io/fortune +-- .info -- +{"Version":"v1.0.0"} +-- fortune.go -- +package main + +import "rsc.io/quote" + +func main() { + println(quote.Hello()) +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt new file mode 100644 index 00000000000..cfa91f08a5d --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt @@ -0,0 +1,15 @@ +rsc.io/fortune v2.0.0 +written by hand + +-- .mod -- +module rsc.io/fortune/v2 +-- .info -- +{"Version":"v2.0.0"} +-- fortune.go -- +package main + +import "rsc.io/quote" + +func main() { + println(quote.Hello()) +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180214005133-e7a685a342c0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180214005133-e7a685a342c0.txt new file mode 100644 index 00000000000..8ae173e7aec --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180214005133-e7a685a342c0.txt @@ -0,0 +1,60 @@ +rsc.io/quote@e7a685a342 + +-- .mod -- +module "rsc.io/quote" +-- .info -- +{"Version":"v0.0.0-20180214005133-e7a685a342c0","Name":"e7a685a342c001acc3eb7f5eafa82980480042c7","Short":"e7a685a342c0","Time":"2018-02-14T00:51:33Z"} +-- go.mod -- +module "rsc.io/quote" +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +// Hello returns a greeting. +func Hello() string { + return "Hello, world." +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func Go() string { + return "Don't communicate by sharing memory, share memory by communicating." +} +-- quote_test.go -- +// 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 quote + +import "testing" + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory. Share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180214005840-23179ee8a569.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180214005840-23179ee8a569.txt new file mode 100644 index 00000000000..bc626bac7a4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180214005840-23179ee8a569.txt @@ -0,0 +1,86 @@ +rsc.io/quote@v0.0.0-20180214005840-23179ee8a569 + +-- .mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- .info -- +{"Version":"v0.0.0-20180214005840-23179ee8a569","Name":"23179ee8a569bb05d896ae05c6503ec69a19f99f","Short":"23179ee8a569","Time":"2018-02-14T00:58:40Z"} +-- go.mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/sampler" + +// Hello returns a greeting. +func Hello() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func Go() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180628003336-dd9747d19b04.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180628003336-dd9747d19b04.txt new file mode 100644 index 00000000000..bbc8097dc3a --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180628003336-dd9747d19b04.txt @@ -0,0 +1,100 @@ +rsc.io/quote@dd9747d + +-- .mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- .info -- +{"Version":"v0.0.0-20180628003336-dd9747d19b04","Name":"dd9747d19b041365fbddf0399ddba6bff5eb1b3e","Short":"dd9747d19b04","Time":"2018-06-28T00:33:36Z"} +-- buggy/buggy_test.go -- +// 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 buggy + +import "testing" + +func Test(t *testing.T) { + t.Fatal("buggy!") +} +-- go.mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/sampler" + +AN EVEN WORSE CHANGE! + +// Hello returns a greeting. +func Hello() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func Go() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709153244-fd906ed3b100.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709153244-fd906ed3b100.txt new file mode 100644 index 00000000000..e461ed4231e --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709153244-fd906ed3b100.txt @@ -0,0 +1,86 @@ +rsc.io/quote@v2.0.0 + +-- .mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- .info -- +{"Version":"v0.0.0-20180709153244-fd906ed3b100","Name":"fd906ed3b100e47181ffa9ec36d82294525c9109","Short":"fd906ed3b100","Time":"2018-07-09T15:32:44Z"} +-- go.mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/sampler" + +// Hello returns a greeting. +func HelloV2() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func GlassV2() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func GoV2() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func OptV2() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709160352-0d003b9c4bfa.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709160352-0d003b9c4bfa.txt new file mode 100644 index 00000000000..c1d511fda71 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709160352-0d003b9c4bfa.txt @@ -0,0 +1,98 @@ +rsc.io/quote@v0.0.0-20180709160352-0d003b9c4bfa + +-- .mod -- +module rsc.io/quote + +require rsc.io/sampler v1.3.0 +-- .info -- +{"Version":"v0.0.0-20180709160352-0d003b9c4bfa","Name":"0d003b9c4bfac881641be8eb1598b782a467a97f","Short":"0d003b9c4bfa","Time":"2018-07-09T16:03:52Z"} +-- buggy/buggy_test.go -- +// 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 buggy + +import "testing" + +func Test(t *testing.T) { + t.Fatal("buggy!") +} +-- go.mod -- +module rsc.io/quote + +require rsc.io/sampler v1.3.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/quote/v2" + +// Hello returns a greeting. +func Hello() string { + return quote.HelloV2() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return quote.GlassV2() +} + +// Go returns a Go proverb. +func Go() string { + return quote.GoV2() +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return quote.OptV2() +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709162749-b44a0b17b2d1.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709162749-b44a0b17b2d1.txt new file mode 100644 index 00000000000..f7f794d76dd --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709162749-b44a0b17b2d1.txt @@ -0,0 +1,104 @@ +rsc.io/quote@v0.0.0-20180709162749-b44a0b17b2d1 + +-- .mod -- +module rsc.io/quote + +require ( + rsc.io/quote/v2 v2.0.1 + rsc.io/sampler v1.3.0 +) +-- .info -- +{"Version":"v0.0.0-20180709162749-b44a0b17b2d1","Name":"b44a0b17b2d1fe4c98a8d0e7a68c9bf9e762799a","Short":"b44a0b17b2d1","Time":"2018-07-09T16:27:49Z"} +-- buggy/buggy_test.go -- +// 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 buggy + +import "testing" + +func Test(t *testing.T) { + t.Fatal("buggy!") +} +-- go.mod -- +module rsc.io/quote + +require ( + rsc.io/quote/v2 v2.0.1 + rsc.io/sampler v1.3.0 +) +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/quote/v2" + +// Hello returns a greeting. +func Hello() string { + return quote.HelloV2() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return quote.GlassV2() +} + +// Go returns a Go proverb. +func Go() string { + return quote.GoV2() +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return quote.OptV2() +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709162816-fe488b867524.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709162816-fe488b867524.txt new file mode 100644 index 00000000000..2d5d8b4e72a --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709162816-fe488b867524.txt @@ -0,0 +1,104 @@ +rsc.io/quote@v0.0.0-20180709162816-fe488b867524 + +-- .mod -- +module rsc.io/quote + +require ( + rsc.io/quote/v2 v2.0.1 + rsc.io/sampler v1.3.0 +) +-- .info -- +{"Version":"v0.0.0-20180709162816-fe488b867524","Name":"fe488b867524806e861c3f4f43ae6946a42ca3f1","Short":"fe488b867524","Time":"2018-07-09T16:28:16Z"} +-- buggy/buggy_test.go -- +// 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 buggy + +import "testing" + +func Test(t *testing.T) { + t.Fatal("buggy!") +} +-- go.mod -- +module rsc.io/quote + +require ( + rsc.io/quote/v2 v2.0.1 + rsc.io/sampler v1.3.0 +) +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/quote/v2" + +// Hello returns a greeting. +func Hello() string { + return quote.HelloV2() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return quote.GlassV2() +} + +// Go returns a Go proverb. +func Go() string { + return quote.GoV2() +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return quote.OptV2() +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709162918-a91498bed0a7.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709162918-a91498bed0a7.txt new file mode 100644 index 00000000000..853a8c2a1ac --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180709162918-a91498bed0a7.txt @@ -0,0 +1,98 @@ +rsc.io/quote@v0.0.0-20180709162918-a91498bed0a7 + +-- .mod -- +module rsc.io/quote + +require rsc.io/sampler v1.3.0 +-- .info -- +{"Version":"v0.0.0-20180709162918-a91498bed0a7","Name":"a91498bed0a73d4bb9c1fb2597925f7883bc40a7","Short":"a91498bed0a7","Time":"2018-07-09T16:29:18Z"} +-- buggy/buggy_test.go -- +// 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 buggy + +import "testing" + +func Test(t *testing.T) { + t.Fatal("buggy!") +} +-- go.mod -- +module rsc.io/quote + +require rsc.io/sampler v1.3.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/quote/v3" + +// Hello returns a greeting. +func Hello() string { + return quote.HelloV3() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return quote.GlassV3() +} + +// Go returns a Go proverb. +func Go() string { + return quote.GoV3() +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return quote.OptV3() +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180710144737-5d9f230bcfba.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180710144737-5d9f230bcfba.txt new file mode 100644 index 00000000000..2ebeac39714 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v0.0.0-20180710144737-5d9f230bcfba.txt @@ -0,0 +1,104 @@ +rsc.io/quote@v0.0.0-20180710144737-5d9f230bcfba + +-- .mod -- +module rsc.io/quote + +require ( + rsc.io/quote/v3 v3.0.0 + rsc.io/sampler v1.3.0 +) +-- .info -- +{"Version":"v0.0.0-20180710144737-5d9f230bcfba","Name":"5d9f230bcfbae514bb6c2215694c2ce7273fc604","Short":"5d9f230bcfba","Time":"2018-07-10T14:47:37Z"} +-- buggy/buggy_test.go -- +// 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 buggy + +import "testing" + +func Test(t *testing.T) { + t.Fatal("buggy!") +} +-- go.mod -- +module rsc.io/quote + +require ( + rsc.io/quote/v3 v3.0.0 + rsc.io/sampler v1.3.0 +) +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/quote/v3" + +// Hello returns a greeting. +func Hello() string { + return quote.HelloV3() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return quote.GlassV3() +} + +// Go returns a Go proverb. +func Go() string { + return quote.GoV3() +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return quote.OptV3() +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.0.0.txt new file mode 100644 index 00000000000..9a079374445 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.0.0.txt @@ -0,0 +1,35 @@ +rsc.io/quote@v1.0.0 + +-- .mod -- +module "rsc.io/quote" +-- .info -- +{"Version":"v1.0.0","Name":"f488df80bcdbd3e5bafdc24ad7d1e79e83edd7e6","Short":"f488df80bcdb","Time":"2018-02-14T00:45:20Z"} +-- go.mod -- +module "rsc.io/quote" +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +// Hello returns a greeting. +func Hello() string { + return "Hello, world." +} +-- quote_test.go -- +// 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 quote + +import "testing" + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.1.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.1.0.txt new file mode 100644 index 00000000000..0c416053901 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.1.0.txt @@ -0,0 +1,48 @@ +rsc.io/quote@v1.1.0 + +-- .mod -- +module "rsc.io/quote" +-- .info -- +{"Version":"v1.1.0","Name":"cfd7145f43f92a8d56b4a3dd603795a3291381a9","Short":"cfd7145f43f9","Time":"2018-02-14T00:46:44Z"} +-- go.mod -- +module "rsc.io/quote" +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +// Hello returns a greeting. +func Hello() string { + return "Hello, world." +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} +-- quote_test.go -- +// 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 quote + +import "testing" + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.2.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.2.0.txt new file mode 100644 index 00000000000..e714f0b9137 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.2.0.txt @@ -0,0 +1,61 @@ +rsc.io/quote@v1.2.0 + +-- .mod -- +module "rsc.io/quote" +-- .info -- +{"Version":"v1.2.0","Name":"d8a3de91045c932a1c71e545308fe97571d6d65c","Short":"d8a3de91045c","Time":"2018-02-14T00:47:51Z"} +-- go.mod -- +module "rsc.io/quote" +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +// Hello returns a greeting. +func Hello() string { + return "Hello, world." +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func Go() string { + return "Don't communicate by sharing memory, share memory by communicating." +} +-- quote_test.go -- +// 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 quote + +import "testing" + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +// Go returns a Go proverb. +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory. Share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.2.1.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.2.1.txt new file mode 100644 index 00000000000..89d5191d3a0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.2.1.txt @@ -0,0 +1,60 @@ +rsc.io/quote@v1.2.1 + +-- .mod -- +module "rsc.io/quote" +-- .info -- +{"Version":"v1.2.1","Name":"5c1f03b64ab7aa958798a569a31924655dc41e76","Short":"5c1f03b64ab7","Time":"2018-02-14T00:54:20Z"} +-- go.mod -- +module "rsc.io/quote" +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +// Hello returns a greeting. +func Hello() string { + return "Hello, world." +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func Go() string { + return "Don't communicate by sharing memory, share memory by communicating." +} +-- quote_test.go -- +// 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 quote + +import "testing" + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.3.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.3.0.txt new file mode 100644 index 00000000000..d62766c7d2b --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.3.0.txt @@ -0,0 +1,73 @@ +rsc.io/quote@v1.3.0 + +-- .mod -- +module "rsc.io/quote" +-- .info -- +{"Version":"v1.3.0","Name":"84de74b35823c1e49634f2262f1a58cfc951ebae","Short":"84de74b35823","Time":"2018-02-14T00:54:53Z"} +-- go.mod -- +module "rsc.io/quote" +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +// Hello returns a greeting. +func Hello() string { + return "Hello, world." +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func Go() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} +-- quote_test.go -- +// 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 quote + +import "testing" + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.4.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.4.0.txt new file mode 100644 index 00000000000..698ff8de812 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.4.0.txt @@ -0,0 +1,79 @@ +rsc.io/quote@v1.4.0 + +-- .mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.0.0 +-- .info -- +{"Version":"v1.4.0","Name":"19e8b977bd2f437798c2cc2dcfe8a1c0f169481b","Short":"19e8b977bd2f","Time":"2018-02-14T00:56:05Z"} +-- go.mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.0.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/sampler" + +// Hello returns a greeting. +func Hello() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func Go() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} +-- quote_test.go -- +// 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 quote + +import "testing" + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.0.txt new file mode 100644 index 00000000000..e7fcdbccff5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.0.txt @@ -0,0 +1,79 @@ +rsc.io/quote@v1.5.0 + +-- .mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- .info -- +{"Version":"v1.5.0","Name":"3ba1e30dc83bd52c990132b9dfb1688a9d22de13","Short":"3ba1e30dc83b","Time":"2018-02-14T00:58:15Z"} +-- go.mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/sampler" + +// Hello returns a greeting. +func Hello() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func Go() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} +-- quote_test.go -- +// 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 quote + +import "testing" + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.1.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.1.txt new file mode 100644 index 00000000000..eed051bea04 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.1.txt @@ -0,0 +1,86 @@ +rsc.io/quote@23179ee8a569 + +-- .mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- .info -- +{"Version":"v1.5.1","Name":"23179ee8a569bb05d896ae05c6503ec69a19f99f","Short":"23179ee8a569","Time":"2018-02-14T00:58:40Z"} +-- go.mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/sampler" + +// Hello returns a greeting. +func Hello() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func Go() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.2.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.2.txt new file mode 100644 index 00000000000..8671f6fe772 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.2.txt @@ -0,0 +1,98 @@ +rsc.io/quote@v1.5.2 + +-- .mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- .info -- +{"Version":"v1.5.2","Name":"c4d4236f92427c64bfbcf1cc3f8142ab18f30b22","Short":"c4d4236f9242","Time":"2018-02-14T15:44:20Z"} +-- buggy/buggy_test.go -- +// 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 buggy + +import "testing" + +func Test(t *testing.T) { + t.Fatal("buggy!") +} +-- go.mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/sampler" + +// Hello returns a greeting. +func Hello() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func Go() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.3-pre1.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.3-pre1.txt new file mode 100644 index 00000000000..212ef13aaf8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v1.5.3-pre1.txt @@ -0,0 +1,100 @@ +rsc.io/quote@v1.5.3-pre1 + +-- .mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- .info -- +{"Version":"v1.5.3-pre1","Name":"2473dfd877c95382420e47686aa9076bf58c79e0","Short":"2473dfd877c9","Time":"2018-06-28T00:32:53Z"} +-- buggy/buggy_test.go -- +// 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 buggy + +import "testing" + +func Test(t *testing.T) { + t.Fatal("buggy!") +} +-- go.mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/sampler" + +// A CHANGE! + +// Hello returns a greeting. +func Hello() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func Glass() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func Go() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func Opt() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v2.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v2.0.0.txt new file mode 100644 index 00000000000..e461ed4231e --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v2.0.0.txt @@ -0,0 +1,86 @@ +rsc.io/quote@v2.0.0 + +-- .mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- .info -- +{"Version":"v0.0.0-20180709153244-fd906ed3b100","Name":"fd906ed3b100e47181ffa9ec36d82294525c9109","Short":"fd906ed3b100","Time":"2018-07-09T15:32:44Z"} +-- go.mod -- +module "rsc.io/quote" + +require "rsc.io/sampler" v1.3.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/sampler" + +// Hello returns a greeting. +func HelloV2() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func GlassV2() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func GoV2() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func OptV2() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v2_v2.0.1.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v2_v2.0.1.txt new file mode 100644 index 00000000000..d51128c46b9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v2_v2.0.1.txt @@ -0,0 +1,86 @@ +rsc.io/quote/v2@v2.0.1 + +-- .mod -- +module rsc.io/quote/v2 + +require rsc.io/sampler v1.3.0 +-- .info -- +{"Version":"v2.0.1","Name":"754f68430672776c84704e2d10209a6ec700cd64","Short":"754f68430672","Time":"2018-07-09T16:25:34Z"} +-- go.mod -- +module rsc.io/quote/v2 + +require rsc.io/sampler v1.3.0 +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/sampler" + +// Hello returns a greeting. +func HelloV2() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func GlassV2() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func GoV2() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func OptV2() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} +-- quote_test.go -- +// 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 quote + +import ( + "os" + "testing" +) + +func init() { + os.Setenv("LC_ALL", "en") +} + +func TestHello(t *testing.T) { + hello := "Hello, world." + if out := Hello(); out != hello { + t.Errorf("Hello() = %q, want %q", out, hello) + } +} + +func TestGlass(t *testing.T) { + glass := "I can eat glass and it doesn't hurt me." + if out := Glass(); out != glass { + t.Errorf("Glass() = %q, want %q", out, glass) + } +} + +func TestGo(t *testing.T) { + go1 := "Don't communicate by sharing memory, share memory by communicating." + if out := Go(); out != go1 { + t.Errorf("Go() = %q, want %q", out, go1) + } +} + +func TestOpt(t *testing.T) { + opt := "If a program is too slow, it must have a loop." + if out := Opt(); out != opt { + t.Errorf("Opt() = %q, want %q", out, opt) + } +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v3_v3.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v3_v3.0.0.txt new file mode 100644 index 00000000000..0afe1f05199 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_quote_v3_v3.0.0.txt @@ -0,0 +1,45 @@ +rsc.io/quote/v3@v3.0.0 + +-- .mod -- +module rsc.io/quote/v3 + +require rsc.io/sampler v1.3.0 + +-- .info -- +{"Version":"v3.0.0","Name":"d88915d7e77ed0fd35d0a022a2f244e2202fd8c8","Short":"d88915d7e77e","Time":"2018-07-09T15:34:46Z"} +-- go.mod -- +module rsc.io/quote/v3 + +require rsc.io/sampler v1.3.0 + +-- quote.go -- +// 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 quote collects pithy sayings. +package quote // import "rsc.io/quote" + +import "rsc.io/sampler" + +// Hello returns a greeting. +func HelloV3() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func GlassV3() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a Go proverb. +func GoV3() string { + return "Don't communicate by sharing memory, share memory by communicating." +} + +// Opt returns an optimization truth. +func OptV3() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.0.0.txt new file mode 100644 index 00000000000..c4b6a71c88c --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.0.0.txt @@ -0,0 +1,20 @@ +rsc.io/sampler@v1.0.0 + +-- .mod -- +module "rsc.io/sampler" +-- .info -- +{"Version":"v1.0.0","Name":"60bef405c52117ad21d2adb10872b95cf17f8fca","Short":"60bef405c521","Time":"2018-02-13T18:05:54Z"} +-- go.mod -- +module "rsc.io/sampler" +-- sampler.go -- +// 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 sampler shows simple texts. +package sampler // import "rsc.io/sampler" + +// Hello returns a greeting. +func Hello() string { + return "Hello, world." +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.2.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.2.0.txt new file mode 100644 index 00000000000..98c35fa2389 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.2.0.txt @@ -0,0 +1,138 @@ +rsc.io/sampler@v1.2.0 + +-- .mod -- +module "rsc.io/sampler" + +require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c +-- .info -- +{"Version":"v1.2.0","Name":"25f24110b153246056eccc14a3a4cd81afaff586","Short":"25f24110b153","Time":"2018-02-13T18:13:45Z"} +-- go.mod -- +module "rsc.io/sampler" + +require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c +-- hello.go -- +// 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. + +// Translations by Google Translate. + +package sampler + +var hello = newText(` + +English: en: Hello, world. +French: fr: Bonjour le monde. +Spanish: es: Hola Mundo. + +`) +-- hello_test.go -- +// 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 sampler + +import ( + "testing" + + "golang.org/x/text/language" +) + +var helloTests = []struct { + prefs []language.Tag + text string +}{ + { + []language.Tag{language.Make("en-US"), language.Make("fr")}, + "Hello, world.", + }, + { + []language.Tag{language.Make("fr"), language.Make("en-US")}, + "Bonjour la monde.", + }, +} + +func TestHello(t *testing.T) { + for _, tt := range helloTests { + text := Hello(tt.prefs...) + if text != tt.text { + t.Errorf("Hello(%v) = %q, want %q", tt.prefs, text, tt.text) + } + } +} +-- sampler.go -- +// 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 sampler shows simple texts. +package sampler // import "rsc.io/sampler" + +import ( + "os" + "strings" + + "golang.org/x/text/language" +) + +// DefaultUserPrefs returns the default user language preferences. +// It consults the $LC_ALL, $LC_MESSAGES, and $LANG environment +// variables, in that order. +func DefaultUserPrefs() []language.Tag { + var prefs []language.Tag + for _, k := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} { + if env := os.Getenv(k); env != "" { + prefs = append(prefs, language.Make(env)) + } + } + return prefs +} + +// Hello returns a localized greeting. +// If no prefs are given, Hello uses DefaultUserPrefs. +func Hello(prefs ...language.Tag) string { + if len(prefs) == 0 { + prefs = DefaultUserPrefs() + } + return hello.find(prefs) +} + +// A text is a localized text. +type text struct { + byTag map[string]string + matcher language.Matcher +} + +// newText creates a new localized text, given a list of translations. +func newText(s string) *text { + t := &text{ + byTag: make(map[string]string), + } + var tags []language.Tag + for _, line := range strings.Split(s, "\n") { + line = strings.TrimSpace(line) + if line == "" { + continue + } + f := strings.Split(line, ": ") + if len(f) != 3 { + continue + } + tag := language.Make(f[1]) + tags = append(tags, tag) + t.byTag[tag.String()] = f[2] + } + t.matcher = language.NewMatcher(tags) + return t +} + +// find finds the text to use for the given language tag preferences. +func (t *text) find(prefs []language.Tag) string { + tag, _, _ := t.matcher.Match(prefs...) + s := t.byTag[tag.String()] + if strings.HasPrefix(s, "RTL ") { + s = "\u200F" + strings.TrimPrefix(s, "RTL ") + "\u200E" + } + return s +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.2.1.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.2.1.txt new file mode 100644 index 00000000000..00b71bf0d59 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.2.1.txt @@ -0,0 +1,134 @@ +generated by ./addmod.bash rsc.io/sampler@v1.2.1 + +-- .mod -- +module "rsc.io/sampler" + +require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c +-- .info -- +{"Version":"v1.2.1","Name":"cac3af4f8a0ab40054fa6f8d423108a63a1255bb","Short":"cac3af4f8a0a","Time":"2018-02-13T18:16:22Z"}EOF +-- hello.go -- +// 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. + +// Translations by Google Translate. + +package sampler + +var hello = newText(` + +English: en: Hello, world. +French: fr: Bonjour le monde. +Spanish: es: Hola Mundo. + +`) +-- hello_test.go -- +// 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 sampler + +import ( + "testing" + + "golang.org/x/text/language" +) + +var helloTests = []struct { + prefs []language.Tag + text string +}{ + { + []language.Tag{language.Make("en-US"), language.Make("fr")}, + "Hello, world.", + }, + { + []language.Tag{language.Make("fr"), language.Make("en-US")}, + "Bonjour le monde.", + }, +} + +func TestHello(t *testing.T) { + for _, tt := range helloTests { + text := Hello(tt.prefs...) + if text != tt.text { + t.Errorf("Hello(%v) = %q, want %q", tt.prefs, text, tt.text) + } + } +} +-- sampler.go -- +// 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 sampler shows simple texts. +package sampler // import "rsc.io/sampler" + +import ( + "os" + "strings" + + "golang.org/x/text/language" +) + +// DefaultUserPrefs returns the default user language preferences. +// It consults the $LC_ALL, $LC_MESSAGES, and $LANG environment +// variables, in that order. +func DefaultUserPrefs() []language.Tag { + var prefs []language.Tag + for _, k := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} { + if env := os.Getenv(k); env != "" { + prefs = append(prefs, language.Make(env)) + } + } + return prefs +} + +// Hello returns a localized greeting. +// If no prefs are given, Hello uses DefaultUserPrefs. +func Hello(prefs ...language.Tag) string { + if len(prefs) == 0 { + prefs = DefaultUserPrefs() + } + return hello.find(prefs) +} + +// A text is a localized text. +type text struct { + byTag map[string]string + matcher language.Matcher +} + +// newText creates a new localized text, given a list of translations. +func newText(s string) *text { + t := &text{ + byTag: make(map[string]string), + } + var tags []language.Tag + for _, line := range strings.Split(s, "\n") { + line = strings.TrimSpace(line) + if line == "" { + continue + } + f := strings.Split(line, ": ") + if len(f) != 3 { + continue + } + tag := language.Make(f[1]) + tags = append(tags, tag) + t.byTag[tag.String()] = f[2] + } + t.matcher = language.NewMatcher(tags) + return t +} + +// find finds the text to use for the given language tag preferences. +func (t *text) find(prefs []language.Tag) string { + tag, _, _ := t.matcher.Match(prefs...) + s := t.byTag[tag.String()] + if strings.HasPrefix(s, "RTL ") { + s = "\u200F" + strings.TrimPrefix(s, "RTL ") + "\u200E" + } + return s +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.3.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.3.0.txt new file mode 100644 index 00000000000..febe51fd9a9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.3.0.txt @@ -0,0 +1,202 @@ +rsc.io/sampler@v1.3.0 + +-- .mod -- +module "rsc.io/sampler" + +require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c +-- .info -- +{"Version":"v1.3.0","Name":"0cc034b51e57ed7832d4c67d526f75a900996e5c","Short":"0cc034b51e57","Time":"2018-02-13T19:05:03Z"} +-- glass.go -- +// 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. + +// Translations from Frank da Cruz, Ethan Mollick, and many others. +// See http://kermitproject.org/utf8.html. +// http://www.oocities.org/nodotus/hbglass.html +// https://en.wikipedia.org/wiki/I_Can_Eat_Glass + +package sampler + +var glass = newText(` + +English: en: I can eat glass and it doesn't hurt me. +French: fr: Je peux manger du verre, ça ne me fait pas mal. +Spanish: es: Puedo comer vidrio, no me hace daño. + +`) +-- glass_test.go -- +// 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 sampler + +import ( + "testing" + + "golang.org/x/text/language" + _ "rsc.io/testonly" +) + +var glassTests = []struct { + prefs []language.Tag + text string +}{ + { + []language.Tag{language.Make("en-US"), language.Make("fr")}, + "I can eat glass and it doesn't hurt me.", + }, + { + []language.Tag{language.Make("fr"), language.Make("en-US")}, + "Je peux manger du verre, ça ne me fait pas mal.", + }, +} + +func TestGlass(t *testing.T) { + for _, tt := range glassTests { + text := Glass(tt.prefs...) + if text != tt.text { + t.Errorf("Glass(%v) = %q, want %q", tt.prefs, text, tt.text) + } + } +} +-- go.mod -- +module "rsc.io/sampler" + +require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c +-- hello.go -- +// 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. + +// Translations by Google Translate. + +package sampler + +var hello = newText(` + +English: en: Hello, world. +French: fr: Bonjour le monde. +Spanish: es: Hola Mundo. + +`) +-- hello_test.go -- +// 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 sampler + +import ( + "testing" + + "golang.org/x/text/language" +) + +var helloTests = []struct { + prefs []language.Tag + text string +}{ + { + []language.Tag{language.Make("en-US"), language.Make("fr")}, + "Hello, world.", + }, + { + []language.Tag{language.Make("fr"), language.Make("en-US")}, + "Bonjour le monde.", + }, +} + +func TestHello(t *testing.T) { + for _, tt := range helloTests { + text := Hello(tt.prefs...) + if text != tt.text { + t.Errorf("Hello(%v) = %q, want %q", tt.prefs, text, tt.text) + } + } +} +-- sampler.go -- +// 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 sampler shows simple texts. +package sampler // import "rsc.io/sampler" + +import ( + "os" + "strings" + + "golang.org/x/text/language" +) + +// DefaultUserPrefs returns the default user language preferences. +// It consults the $LC_ALL, $LC_MESSAGES, and $LANG environment +// variables, in that order. +func DefaultUserPrefs() []language.Tag { + var prefs []language.Tag + for _, k := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} { + if env := os.Getenv(k); env != "" { + prefs = append(prefs, language.Make(env)) + } + } + return prefs +} + +// Hello returns a localized greeting. +// If no prefs are given, Hello uses DefaultUserPrefs. +func Hello(prefs ...language.Tag) string { + if len(prefs) == 0 { + prefs = DefaultUserPrefs() + } + return hello.find(prefs) +} + +// Glass returns a localized silly phrase. +// If no prefs are given, Glass uses DefaultUserPrefs. +func Glass(prefs ...language.Tag) string { + if len(prefs) == 0 { + prefs = DefaultUserPrefs() + } + return glass.find(prefs) +} + +// A text is a localized text. +type text struct { + byTag map[string]string + matcher language.Matcher +} + +// newText creates a new localized text, given a list of translations. +func newText(s string) *text { + t := &text{ + byTag: make(map[string]string), + } + var tags []language.Tag + for _, line := range strings.Split(s, "\n") { + line = strings.TrimSpace(line) + if line == "" { + continue + } + f := strings.Split(line, ": ") + if len(f) != 3 { + continue + } + tag := language.Make(f[1]) + tags = append(tags, tag) + t.byTag[tag.String()] = f[2] + } + t.matcher = language.NewMatcher(tags) + return t +} + +// find finds the text to use for the given language tag preferences. +func (t *text) find(prefs []language.Tag) string { + tag, _, _ := t.matcher.Match(prefs...) + s := t.byTag[tag.String()] + if strings.HasPrefix(s, "RTL ") { + s = "\u200F" + strings.TrimPrefix(s, "RTL ") + "\u200E" + } + return s +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.3.1.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.3.1.txt new file mode 100644 index 00000000000..a293f108696 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.3.1.txt @@ -0,0 +1,201 @@ +rsc.io/sampler@v1.3.1 + +-- .mod -- +module "rsc.io/sampler" + +require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c +-- .info -- +{"Version":"v1.3.1","Name":"f545d0289d06e2add4556ea6a15fc4938014bf87","Short":"f545d0289d06","Time":"2018-02-14T16:34:12Z"} +-- glass.go -- +// 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. + +// Translations from Frank da Cruz, Ethan Mollick, and many others. +// See http://kermitproject.org/utf8.html. +// http://www.oocities.org/nodotus/hbglass.html +// https://en.wikipedia.org/wiki/I_Can_Eat_Glass + +package sampler + +var glass = newText(` + +English: en: I can eat glass and it doesn't hurt me. +French: fr: Je peux manger du verre, ça ne me fait pas mal. +Spanish: es: Puedo comer vidrio, no me hace daño. + +`) +-- glass_test.go -- +// 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 sampler + +import ( + "testing" + + "golang.org/x/text/language" +) + +var glassTests = []struct { + prefs []language.Tag + text string +}{ + { + []language.Tag{language.Make("en-US"), language.Make("fr")}, + "I can eat glass and it doesn't hurt me.", + }, + { + []language.Tag{language.Make("fr"), language.Make("en-US")}, + "Je peux manger du verre, ça ne me fait pas mal.", + }, +} + +func TestGlass(t *testing.T) { + for _, tt := range glassTests { + text := Glass(tt.prefs...) + if text != tt.text { + t.Errorf("Glass(%v) = %q, want %q", tt.prefs, text, tt.text) + } + } +} +-- go.mod -- +module "rsc.io/sampler" + +require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c +-- hello.go -- +// 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. + +// Translations by Google Translate. + +package sampler + +var hello = newText(` + +English: en: Hello, world. +French: fr: Bonjour le monde. +Spanish: es: Hola Mundo. + +`) +-- hello_test.go -- +// 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 sampler + +import ( + "testing" + + "golang.org/x/text/language" +) + +var helloTests = []struct { + prefs []language.Tag + text string +}{ + { + []language.Tag{language.Make("en-US"), language.Make("fr")}, + "Hello, world.", + }, + { + []language.Tag{language.Make("fr"), language.Make("en-US")}, + "Bonjour le monde.", + }, +} + +func TestHello(t *testing.T) { + for _, tt := range helloTests { + text := Hello(tt.prefs...) + if text != tt.text { + t.Errorf("Hello(%v) = %q, want %q", tt.prefs, text, tt.text) + } + } +} +-- sampler.go -- +// 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 sampler shows simple texts in a variety of languages. +package sampler // import "rsc.io/sampler" + +import ( + "os" + "strings" + + "golang.org/x/text/language" +) + +// DefaultUserPrefs returns the default user language preferences. +// It consults the $LC_ALL, $LC_MESSAGES, and $LANG environment +// variables, in that order. +func DefaultUserPrefs() []language.Tag { + var prefs []language.Tag + for _, k := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} { + if env := os.Getenv(k); env != "" { + prefs = append(prefs, language.Make(env)) + } + } + return prefs +} + +// Hello returns a localized greeting. +// If no prefs are given, Hello uses DefaultUserPrefs. +func Hello(prefs ...language.Tag) string { + if len(prefs) == 0 { + prefs = DefaultUserPrefs() + } + return hello.find(prefs) +} + +// Glass returns a localized silly phrase. +// If no prefs are given, Glass uses DefaultUserPrefs. +func Glass(prefs ...language.Tag) string { + if len(prefs) == 0 { + prefs = DefaultUserPrefs() + } + return glass.find(prefs) +} + +// A text is a localized text. +type text struct { + byTag map[string]string + matcher language.Matcher +} + +// newText creates a new localized text, given a list of translations. +func newText(s string) *text { + t := &text{ + byTag: make(map[string]string), + } + var tags []language.Tag + for _, line := range strings.Split(s, "\n") { + line = strings.TrimSpace(line) + if line == "" { + continue + } + f := strings.Split(line, ": ") + if len(f) != 3 { + continue + } + tag := language.Make(f[1]) + tags = append(tags, tag) + t.byTag[tag.String()] = f[2] + } + t.matcher = language.NewMatcher(tags) + return t +} + +// find finds the text to use for the given language tag preferences. +func (t *text) find(prefs []language.Tag) string { + tag, _, _ := t.matcher.Match(prefs...) + s := t.byTag[tag.String()] + if strings.HasPrefix(s, "RTL ") { + s = "\u200F" + strings.TrimPrefix(s, "RTL ") + "\u200E" + } + return s +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.99.99.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.99.99.txt new file mode 100644 index 00000000000..5036d20ab58 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_sampler_v1.99.99.txt @@ -0,0 +1,140 @@ +rsc.io/sampler@v1.99.99 + +-- .mod -- +module "rsc.io/sampler" + +require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c +-- .info -- +{"Version":"v1.99.99","Name":"732a3c400797d8835f2af34a9561f155bef85435","Short":"732a3c400797","Time":"2018-02-13T22:20:19Z"} +-- go.mod -- +module "rsc.io/sampler" + +require "golang.org/x/text" v0.0.0-20170915032832-14c0d48ead0c +-- hello.go -- +// 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. + +// Translations by Google Translate. + +package sampler + +var hello = newText(` + +English: en: 99 bottles of beer on the wall, 99 bottles of beer, ... + +`) +-- hello_test.go -- +// 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 sampler + +import ( + "testing" + + "golang.org/x/text/language" +) + +var helloTests = []struct { + prefs []language.Tag + text string +}{ + { + []language.Tag{language.Make("en-US"), language.Make("fr")}, + "Hello, world.", + }, + { + []language.Tag{language.Make("fr"), language.Make("en-US")}, + "Bonjour le monde.", + }, +} + +func TestHello(t *testing.T) { + for _, tt := range helloTests { + text := Hello(tt.prefs...) + if text != tt.text { + t.Errorf("Hello(%v) = %q, want %q", tt.prefs, text, tt.text) + } + } +} +-- sampler.go -- +// 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 sampler shows simple texts. +package sampler // import "rsc.io/sampler" + +import ( + "os" + "strings" + + "golang.org/x/text/language" +) + +// DefaultUserPrefs returns the default user language preferences. +// It consults the $LC_ALL, $LC_MESSAGES, and $LANG environment +// variables, in that order. +func DefaultUserPrefs() []language.Tag { + var prefs []language.Tag + for _, k := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} { + if env := os.Getenv(k); env != "" { + prefs = append(prefs, language.Make(env)) + } + } + return prefs +} + +// Hello returns a localized greeting. +// If no prefs are given, Hello uses DefaultUserPrefs. +func Hello(prefs ...language.Tag) string { + if len(prefs) == 0 { + prefs = DefaultUserPrefs() + } + return hello.find(prefs) +} + +func Glass() string { + return "I can eat glass and it doesn't hurt me." +} + +// A text is a localized text. +type text struct { + byTag map[string]string + matcher language.Matcher +} + +// newText creates a new localized text, given a list of translations. +func newText(s string) *text { + t := &text{ + byTag: make(map[string]string), + } + var tags []language.Tag + for _, line := range strings.Split(s, "\n") { + line = strings.TrimSpace(line) + if line == "" { + continue + } + f := strings.Split(line, ": ") + if len(f) != 3 { + continue + } + tag := language.Make(f[1]) + tags = append(tags, tag) + t.byTag[tag.String()] = f[2] + } + t.matcher = language.NewMatcher(tags) + return t +} + +// find finds the text to use for the given language tag preferences. +func (t *text) find(prefs []language.Tag) string { + tag, _, _ := t.matcher.Match(prefs...) + s := t.byTag[tag.String()] + if strings.HasPrefix(s, "RTL ") { + s = "\u200F" + strings.TrimPrefix(s, "RTL ") + "\u200E" + } + return s +} diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_testonly_v1.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_testonly_v1.0.0.txt new file mode 100644 index 00000000000..dfb8ca24ec9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/mod/rsc.io_testonly_v1.0.0.txt @@ -0,0 +1,9 @@ +rsc.io/testonly v1.0.0 +written by hand + +-- .mod -- +module rsc.io/testonly +-- .info -- +{"Version":"v1.0.0"} +-- testonly.go -- +package testonly diff --git a/libgo/go/cmd/go/testdata/savedir.go b/libgo/go/cmd/go/testdata/savedir.go new file mode 100644 index 00000000000..48a63188607 --- /dev/null +++ b/libgo/go/cmd/go/testdata/savedir.go @@ -0,0 +1,79 @@ +// 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 + +// Savedir archives a directory tree as a txtar archive printed to standard output. +// +// Usage: +// +// go run savedir.go /path/to/dir >saved.txt +// +// Typically the tree is later extracted during a test with tg.extract("testdata/saved.txt"). +// +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" + "unicode/utf8" + + "../internal/txtar" +) + +func usage() { + fmt.Fprintf(os.Stderr, "usage: go run savedir.go dir >saved.txt\n") + os.Exit(2) +} + +const goCmd = "vgo" + +func main() { + flag.Usage = usage + flag.Parse() + if flag.NArg() != 1 { + usage() + } + + log.SetPrefix("savedir: ") + log.SetFlags(0) + + dir := flag.Arg(0) + + a := new(txtar.Archive) + dir = filepath.Clean(dir) + filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if path == dir { + return nil + } + name := info.Name() + if strings.HasPrefix(name, ".") { + if info.IsDir() { + return filepath.SkipDir + } + return nil + } + if !info.Mode().IsRegular() { + return nil + } + data, err := ioutil.ReadFile(path) + if err != nil { + log.Fatal(err) + } + if !utf8.Valid(data) { + log.Printf("%s: ignoring invalid UTF-8 data", path) + return nil + } + a.Files = append(a.Files, txtar.File{Name: strings.TrimPrefix(path, dir+string(filepath.Separator)), Data: data}) + return nil + }) + + data := txtar.Format(a) + os.Stdout.Write(data) +} diff --git a/libgo/go/cmd/go/testdata/script/README b/libgo/go/cmd/go/testdata/script/README new file mode 100644 index 00000000000..a80233b8c38 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/README @@ -0,0 +1,261 @@ +This directory holds test scripts *.txt run during 'go test cmd/go'. +To run a specific script foo.txt + + go test cmd/go -run=Script/^foo$ + +In general script files should have short names: a few words, not whole sentences. +The first word should be the general category of behavior being tested, +often the name of a go subcommand (list, build, test, ...) or concept (vendor, pattern). + +Each script is a text archive (go doc cmd/go/internal/txtar). +The script begins with an actual command script to run +followed by the content of zero or more supporting files to +create in the script's temporary file system before it starts executing. + +As an example, run_hello.txt says: + + # hello world + go run hello.go + stderr 'hello world' + ! stdout . + + -- hello.go -- + package main + func main() { println("hello world") } + +Each script runs in a fresh temporary work directory tree, available to scripts as $WORK. +Scripts also have access to these other environment variables: + + GOARCH= + GOCACHE= + GOOS= + GOPATH=$WORK/gopath + GOPROXY= + GOROOT= + HOME=/no-home + PATH= + TMPDIR=$WORK/tmp + devnull= + +The environment variable $exe (lowercase) is an empty string on most systems, ".exe" on Windows. + +The scripts supporting files are unpacked relative to $GOPATH/src (aka $WORK/gopath/src) +and then the script begins execution in that directory as well. Thus the example above runs +in $WORK/gopath/src with GOPATH=$WORK/gopath and $WORK/gopath/src/hello.go +containing the listed contents. + +The lines at the top of the script are a sequence of commands to be executed +by a tiny script engine in ../../script_test.go (not the system shell). +The script stops and the overall test fails if any particular command fails. + +Each line is parsed into a sequence of space-separated command words, +with environment variable expansion and # marking an end-of-line comment. +Adding single quotes around text keeps spaces in that text from being treated +as word separators and also disables environment variable expansion. +Inside a single-quoted block of text, a repeated single quote indicates +a literal single quote, as in: + + 'Don''t communicate by sharing memory.' + +A line beginning with # is a comment and conventionally explains what is +being done or tested at the start of a new phase in the script. + +The command prefix ! indicates that the command on the rest of the line +(typically go or a matching predicate) must fail, not succeed. Only certain +commands support this prefix. They are indicated below by [!] in the synopsis. + +The command prefix [cond] indicates that the command on the rest of the line +should only run when the condition is satisfied. The available conditions are: + + - GOOS and GOARCH values, like [386], [windows], and so on. + - Compiler names, like [gccgo], [gc]. + - Test environment details: + - [short] for testing.Short() + - [cgo], [msan], [race] for whether cgo, msan, and the race detector can be used + - [net] for whether the external network can be used + - [link] for testenv.HasLink() + - [symlink] for testenv.HasSymlink() + - [exec:prog] for whether prog is available for execution (found by exec.LookPath) + +A condition can be negated: [!short] means to run the rest of the line +when testing.Short() is false. + +The commands are: + +- cd dir + Change to the given directory for future commands. + +- cmp file1 file2 + Check that the named files have the same content. + By convention, file1 is the actual data and file2 the expected data. + File1 can be "stdout" or "stderr" to use the standard output or standard error + from the most recent exec or go command. + (If the files have differing content, the failure prints a diff.) + +- cp src... dst + Copy the listed files to the target file or existing directory. + +- env [key=value...] + With no arguments, print the environment (useful for debugging). + Otherwise add the listed key=value pairs to the environment. + +- [!] exec program [args...] + Run the given executable program with the arguments. + It must (or must not) succeed. + Note that 'exec' does not terminate the script (unlike in Unix shells). + +- [!] exists [-readonly] file... + Each of the listed files or directories must (or must not) exist. + If -readonly is given, the files or directories must be unwritable. + +- [!] go args... + Run the (test copy of the) go command with the given arguments. + It must (or must not) succeed. + +- [!] grep [-count=N] pattern file + The file's content must (or must not) match the regular expression pattern. + For positive matches, -count=N specifies an exact number of matches to require. + +- mkdir path... + Create the listed directories, if they do not already exists. + +- rm file... + Remove the listed files or directories. + +- skip [message] + Mark the test skipped, including the message if given. + +- [!] stale path... + The packages named by the path arguments must (or must not) + be reported as "stale" by the go command. + +- [!] stderr [-count=N] pattern + Apply the grep command (see above) to the standard error + from the most recent exec or go command. + +- [!] stdout [-count=N] pattern + Apply the grep command (see above) to the standard output + from the most recent exec or go command. + +- stop [message] + Stop the test early (marking it as passing), including the message if given. + +- symlink file -> target + Create file as a symlink to target. The -> (like in ls -l output) is required. + +When TestScript runs a script and the script fails, by default TestScript shows +the execution of the most recent phase of the script (since the last # comment) +and only shows the # comments for earlier phases. For example, here is a +multi-phase script with a bug in it: + + # GOPATH with p1 in d2, p2 in d2 + env GOPATH=$WORK/d1${:}$WORK/d2 + + # build & install p1 + env + go install -i p1 + ! stale p1 + ! stale p2 + + # modify p2 - p1 should appear stale + cp $WORK/p2x.go $WORK/d2/src/p2/p2.go + stale p1 p2 + + # build & install p1 again + go install -i p11 + ! stale p1 + ! stale p2 + + -- $WORK/d1/src/p1/p1.go -- + package p1 + import "p2" + func F() { p2.F() } + -- $WORK/d2/src/p2/p2.go -- + package p2 + func F() {} + -- $WORK/p2x.go -- + package p2 + func F() {} + func G() {} + +The bug is that the final phase installs p11 instead of p1. The test failure looks like: + + $ go test -run=Script + --- FAIL: TestScript (3.75s) + --- FAIL: TestScript/install_rebuild_gopath (0.16s) + script_test.go:223: + # GOPATH with p1 in d2, p2 in d2 (0.000s) + # build & install p1 (0.087s) + # modify p2 - p1 should appear stale (0.029s) + # build & install p1 again (0.022s) + > go install -i p11 + [stderr] + can't load package: package p11: cannot find package "p11" in any of: + /Users/rsc/go/src/p11 (from $GOROOT) + $WORK/d1/src/p11 (from $GOPATH) + $WORK/d2/src/p11 + [exit status 1] + FAIL: unexpected go command failure + + script_test.go:73: failed at testdata/script/install_rebuild_gopath.txt:15 in $WORK/gopath/src + + FAIL + exit status 1 + FAIL cmd/go 4.875s + $ + +Note that the commands in earlier phases have been hidden, so that the relevant +commands are more easily found, and the elapsed time for a completed phase +is shown next to the phase heading. To see the entire execution, use "go test -v", +which also adds an initial environment dump to the beginning of the log. + +Note also that in reported output, the actual name of the per-script temporary directory +has been consistently replaced with the literal string $WORK. + +The cmd/go test flag -testwork (which must appear on the "go test" command line after +standard test flags) causes each test to log the name of its $WORK directory and other +environment variable settings and also to leave that directory behind when it exits, +for manual debugging of failing tests: + + $ go test -run=Script -work + --- FAIL: TestScript (3.75s) + --- FAIL: TestScript/install_rebuild_gopath (0.16s) + script_test.go:223: + WORK=/tmp/cmd-go-test-745953508/script-install_rebuild_gopath + GOARCH= + GOCACHE=/Users/rsc/Library/Caches/go-build + GOOS= + GOPATH=$WORK/gopath + GOROOT=/Users/rsc/go + HOME=/no-home + TMPDIR=$WORK/tmp + exe= + + # GOPATH with p1 in d2, p2 in d2 (0.000s) + # build & install p1 (0.085s) + # modify p2 - p1 should appear stale (0.030s) + # build & install p1 again (0.019s) + > go install -i p11 + [stderr] + can't load package: package p11: cannot find package "p11" in any of: + /Users/rsc/go/src/p11 (from $GOROOT) + $WORK/d1/src/p11 (from $GOPATH) + $WORK/d2/src/p11 + [exit status 1] + FAIL: unexpected go command failure + + script_test.go:73: failed at testdata/script/install_rebuild_gopath.txt:15 in $WORK/gopath/src + + FAIL + exit status 1 + FAIL cmd/go 4.875s + $ + + $ WORK=/tmp/cmd-go-test-745953508/script-install_rebuild_gopath + $ cd $WORK/d1/src/p1 + $ cat p1.go + package p1 + import "p2" + func F() { p2.F() } + $ + diff --git a/libgo/go/cmd/go/testdata/script/binary_only.txt b/libgo/go/cmd/go/testdata/script/binary_only.txt new file mode 100644 index 00000000000..397904efaa8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/binary_only.txt @@ -0,0 +1,10 @@ +# check that error for missing binary-only says where it should be +! go build b +stderr pkg[\\/].*a\.a + +-- a/a.go -- +//go:binary-only-package + +package a +-- b/b.go -- +package b; import "a" diff --git a/libgo/go/cmd/go/testdata/script/build_GOTMPDIR.txt b/libgo/go/cmd/go/testdata/script/build_GOTMPDIR.txt new file mode 100644 index 00000000000..4c387afbbab --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_GOTMPDIR.txt @@ -0,0 +1,11 @@ +# Build should use GOTMPDIR if set. +env GOTMPDIR=$WORK/my-favorite-tmpdir +env GOCACHE=off +mkdir $GOTMPDIR +go build -work hello.go +stderr ^WORK=.*my-favorite-tmpdir + +-- hello.go -- +package main +func main() { println("hello") } + diff --git a/libgo/go/cmd/go/testdata/script/build_cache_compile.txt b/libgo/go/cmd/go/testdata/script/build_cache_compile.txt new file mode 100644 index 00000000000..7db881a2682 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_cache_compile.txt @@ -0,0 +1,18 @@ +# Set up fresh GOCACHE. +env GOCACHE=$WORK/gocache +mkdir $GOCACHE + +# Building trivial non-main package should run compiler the first time. +go build -x lib.go +stderr '(compile|gccgo)( |\.exe).*lib\.go' + +# ... but not again ... +go build -x lib.go +! stderr '(compile|gccgo)( |\.exe).*lib\.go' + +# ... unless we use -a. +go build -a -x lib.go +stderr '(compile|gccgo)( |\.exe)' + +-- lib.go -- +package lib diff --git a/libgo/go/cmd/go/testdata/script/build_cache_link.txt b/libgo/go/cmd/go/testdata/script/build_cache_link.txt new file mode 100644 index 00000000000..61e7ee46d3a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_cache_link.txt @@ -0,0 +1,23 @@ +# Set up fresh GOCACHE. +env GOCACHE=$WORK/gocache +mkdir $GOCACHE + +# Building a main package should run the compiler and linker ... +go build -o $devnull -x main.go +stderr '(compile|gccgo)( |\.exe).*main\.go' +stderr '(link|gccgo)( |\.exe)' + +# ... and then the linker again ... +go build -o $devnull -x main.go +! stderr '(compile|gccgo)( |\.exe).*main\.go' +stderr '(link|gccgo)( |\.exe)' + +# ... but the output binary can serve as a cache. +go build -o main$exe -x main.go +stderr '(link|gccgo)( |\.exe)' +go build -o main$exe -x main.go +! stderr '(link|gccgo)( |\.exe)' + +-- main.go -- +package main +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/build_cache_output.txt b/libgo/go/cmd/go/testdata/script/build_cache_output.txt new file mode 100644 index 00000000000..ee4099e5f35 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/build_cache_output.txt @@ -0,0 +1,63 @@ +[!gc] skip + +# Set up fresh GOCACHE. +env GOCACHE=$WORK/gocache +mkdir $GOCACHE + +# Building a trivial non-main package should run compiler the first time. +go build -x -gcflags=-m lib.go +stderr 'compile( |\.exe"?)' +stderr 'lib.go:2.* can inline f' + +# ... but not the second, even though it still prints the compiler output. +go build -x -gcflags=-m lib.go +! stderr 'compile( |\.exe"?)' +stderr 'lib.go:2.* can inline f' + +# Building a trivial main package should run the compiler and linker the first time. +go build -x -gcflags=-m -ldflags='-v -w' main.go +stderr 'compile( |\.exe"?)' +stderr 'main.go:2.* can inline main' # from compiler +stderr 'link(\.exe"?)? -' +stderr '\d+ symbols' # from linker + +# ... but not the second, even though it still prints the compiler and linker output. +go build -x -gcflags=-m -ldflags='-v -w' main.go +! stderr 'compile( |\.exe"?)' +stderr 'main.go:2.* can inline main' # from compiler +! stderr 'link(\.exe"?)? -' +stderr '\d+ symbols' # from linker + +# Running a test should run the compiler, linker, and the test the first time. +go test -v -x -gcflags=-m -ldflags=-v p_test.go +stderr 'compile( |\.exe"?)' +stderr 'p_test.go:.*can inline Test' # from compile of p_test +stderr 'testmain\.go:.*inlin' # from compile of testmain +stderr 'link(\.exe"?)? -' +stderr '\d+ symbols' # from linker +stderr 'p\.test( |\.exe"?)' +stdout 'TEST' # from test + +# ... but not the second, even though it still prints the compiler, linker, and test output. +go test -v -x -gcflags=-m -ldflags=-v p_test.go +! stderr 'compile( |\.exe"?)' +stderr 'p_test.go:.*can inline Test' # from compile of p_test +stderr 'testmain\.go:.*inlin' # from compile of testmain +! stderr 'link(\.exe"?)? -' +stderr '\d+ symbols' # from linker +! stderr 'p\.test( |\.exe"?)' +stdout 'TEST' # from test + + +-- lib.go -- +package p +func f(x *int) *int { return x } + +-- main.go -- +package main +func main() {} + +-- p_test.go -- +package p +import "testing" +func Test(t *testing.T) {println("TEST")} diff --git a/libgo/go/cmd/go/testdata/script/cover_atomic_pkgall.txt b/libgo/go/cmd/go/testdata/script/cover_atomic_pkgall.txt new file mode 100644 index 00000000000..c122c05cb68 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_atomic_pkgall.txt @@ -0,0 +1,23 @@ +[short] skip + +go test -coverpkg=all -covermode=atomic x +stdout ok[\s\S]+?coverage + +[!race] stop + +go test -coverpkg=all -race x +stdout ok[\s\S]+?coverage + +-- x/x.go -- +package x + +import _ "sync/atomic" + +func F() {} + +-- x/x_test.go -- +package x + +import "testing" + +func TestF(t *testing.T) { F() } diff --git a/libgo/go/cmd/go/testdata/script/cover_pkgall_runtime.txt b/libgo/go/cmd/go/testdata/script/cover_pkgall_runtime.txt new file mode 100644 index 00000000000..5d169d63126 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cover_pkgall_runtime.txt @@ -0,0 +1,21 @@ +# Issue 23882 + +[short] skip + +go test -coverpkg=all x +stdout ok[\s\S]+?coverage + +[!race] stop + +go test -coverpkg=all -race x +stdout ok[\s\S]+?coverage + +-- x/x.go -- +package x +import _ "runtime" +func F() {} + +-- x/x_test.go -- +package x +import "testing" +func TestF(t *testing.T) { F() } diff --git a/libgo/go/cmd/go/testdata/script/cpu_profile_twice.txt b/libgo/go/cmd/go/testdata/script/cpu_profile_twice.txt new file mode 100644 index 00000000000..142d5ee718d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/cpu_profile_twice.txt @@ -0,0 +1,20 @@ +# Issue 23150 + +[short] skip + +go test -o=$WORK/x.test -cpuprofile=$WORK/cpu_profile_twice.out x +rm $WORK/cpu_profile_twice.out + +go test -o=$WORK/x.test -cpuprofile=$WORK/cpu_profile_twice.out x +exists $WORK/cpu_profile_twice.out + + +-- x/x_test.go -- +package x_test +import ( + "testing" + "time" +) +func TestSleep(t *testing.T) { + time.Sleep(10 * time.Millisecond) +} diff --git a/libgo/go/cmd/go/testdata/script/fileline.txt b/libgo/go/cmd/go/testdata/script/fileline.txt new file mode 100644 index 00000000000..cdc3be2df8f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/fileline.txt @@ -0,0 +1,6 @@ +# look for short, relative file:line in error message +! go run ../../gopath/x/y/z/err.go +stderr ^..[\\/]x[\\/]y[\\/]z[\\/]err.go: + +-- ../x/y/z/err.go -- +package main; import "bar" diff --git a/libgo/go/cmd/go/testdata/script/get_with_git_trace.txt b/libgo/go/cmd/go/testdata/script/get_with_git_trace.txt new file mode 100644 index 00000000000..93341a302c8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/get_with_git_trace.txt @@ -0,0 +1,7 @@ +env GIT_TRACE=1 + +[!net] skip +[!exec:git] skip + +# go get should be success when GIT_TRACE set +go get golang.org/x/text diff --git a/libgo/go/cmd/go/testdata/script/goflags.txt b/libgo/go/cmd/go/testdata/script/goflags.txt new file mode 100644 index 00000000000..20de325ac28 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/goflags.txt @@ -0,0 +1,49 @@ +# GOFLAGS sets flags for commands + +env GOFLAGS='-e -f={{.Dir}} --test.benchtime=1s -count=10' +go list asdfasdfasdf # succeeds because of -e +go list runtime +stdout '[\\/]runtime$' + +env GOFLAGS=-race OLDGOARCH=$GOARCH OLDGOOS=$GOOS GOARCH=386 GOOS=linux +! go list runtime +stderr 'race is only supported on' + +env GOARCH=$OLDGOARCH GOOS=$OLDGOOS + +# go env succeeds even though -f={{.Dir}} is inappropriate +go env + +# bad flags are diagnosed +env GOFLAGS=-typoflag +! go list runtime +stderr 'unknown flag -typoflag' + +env GOFLAGS=- +! go list runtime +stderr '^go: parsing \$GOFLAGS: non-flag "-"' + +env GOFLAGS=-- +! go list runtime +stderr '^go: parsing \$GOFLAGS: non-flag "--"' + +env GOFLAGS=---oops +! go list runtime +stderr '^go: parsing \$GOFLAGS: non-flag "---oops"' + +env GOFLAGS=-=noname +! go list runtime +stderr '^go: parsing \$GOFLAGS: non-flag "-=noname"' + +env GOFLAGS=-f +! go list runtime +stderr '^go: flag needs an argument: -f \(from (\$GOFLAGS|%GOFLAGS%)\)$' + +env GOFLAGS=-e=asdf +! go list runtime +stderr '^go: invalid boolean value \"asdf\" for flag -e \(from (\$GOFLAGS|%GOFLAGS%)\)' + +# except in go bug (untested) and go env +go env +stdout GOFLAGS + diff --git a/libgo/go/cmd/go/testdata/script/help.txt b/libgo/go/cmd/go/testdata/script/help.txt new file mode 100644 index 00000000000..cbbd15404b5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/help.txt @@ -0,0 +1,30 @@ +# go help shows overview. +go help +stdout 'Go is a tool' +stdout 'bug.*start a bug report' + +# go help bug shows usage for bug +go help bug +stdout 'usage: go bug' +stdout 'bug report' + +# go bug help is an error (bug takes no arguments) +! go bug help +stderr 'bug takes no arguments' + +# go help mod shows mod subcommands +go help mod +stdout 'go mod ' +stdout tidy + +# go help mod tidy explains tidy +go help mod tidy +stdout 'usage: go mod tidy' + +# go mod help tidy does too +go mod help tidy +stdout 'usage: go mod tidy' + +# go mod --help doesn't print help but at least suggests it. +! go mod --help +stderr 'Run ''go help mod'' for usage.' diff --git a/libgo/go/cmd/go/testdata/script/install_cleans_build.txt b/libgo/go/cmd/go/testdata/script/install_cleans_build.txt new file mode 100644 index 00000000000..b8d322de629 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/install_cleans_build.txt @@ -0,0 +1,22 @@ +# 'go install' with no arguments should clean up after go build +cd mycmd +go build +exists mycmd$exe +go install +! exists mycmd$exe + +# 'go install mycmd' does not clean up, even in the mycmd directory +go build +exists mycmd$exe +go install mycmd +exists mycmd$exe + +# 'go install mycmd' should not clean up in an unrelated current directory either +cd .. +cp mycmd/mycmd$exe mycmd$exe +go install mycmd +exists mycmd$exe + +-- mycmd/main.go -- +package main +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/install_cross_gobin.txt b/libgo/go/cmd/go/testdata/script/install_cross_gobin.txt new file mode 100644 index 00000000000..f85e896f61e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/install_cross_gobin.txt @@ -0,0 +1,25 @@ +cd mycmd +go build mycmd + +[gccgo] stop + +# cross-compile install with implicit GOBIN=$GOPATH/bin can make subdirectory +env GOARCH=386 +[386] env GOARCH=amd64 +env GOOS=linux +go install mycmd +exists $GOPATH/bin/linux_$GOARCH/mycmd + +# cross-compile install with explicit GOBIN cannot make subdirectory +env GOBIN=$WORK/bin +! go install mycmd +! exists $GOBIN/linux_$GOARCH + +# installing standard command should still work +# (should also be mtime update only if cmd/pack is up-to-date). +! stale cmd/pack +[!short] go install cmd/pack + +-- mycmd/x.go -- +package main +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/install_rebuild_gopath.txt b/libgo/go/cmd/go/testdata/script/install_rebuild_gopath.txt new file mode 100644 index 00000000000..d42b07004bf --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/install_rebuild_gopath.txt @@ -0,0 +1,28 @@ +# GOPATH with p1 in d1, p2 in d2 +env GOPATH=$WORK/d1${:}$WORK/d2 + +# build & install p1 +go install -i p1 +! stale p1 p2 + +# modify p2 - p1 should appear stale +cp $WORK/p2x.go $WORK/d2/src/p2/p2.go +stale p1 p2 + +# build & install p1 again +go install -i p1 +! stale p1 p2 + +-- $WORK/d1/src/p1/p1.go -- +package p1 +import "p2" +func F() { p2.F() } + +-- $WORK/d2/src/p2/p2.go -- +package p2 +func F() {} + +-- $WORK/p2x.go -- +package p2 +func F() {} +func G() {} diff --git a/libgo/go/cmd/go/testdata/script/install_rebuild_removed.txt b/libgo/go/cmd/go/testdata/script/install_rebuild_removed.txt new file mode 100644 index 00000000000..e7620a08cae --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/install_rebuild_removed.txt @@ -0,0 +1,42 @@ +# go command should detect package staleness as source file set changes +go install mypkg +! stale mypkg + +# z.go was not compiled; removing it should NOT make mypkg stale +rm mypkg/z.go +! stale mypkg + +# y.go was compiled; removing it should make mypkg stale +rm mypkg/y.go +stale mypkg + +# go command should detect executable staleness too +go install mycmd +! stale mycmd +rm mycmd/z.go +! stale mycmd +rm mycmd/y.go +stale mycmd + +-- mypkg/x.go -- +package mypkg + +-- mypkg/y.go -- +package mypkg + +-- mypkg/z.go -- +// +build missingtag + +package mypkg + +-- mycmd/x.go -- +package main +func main() {} + +-- mycmd/y.go -- +package main + +-- mycmd/z.go -- +// +build missingtag + +package main diff --git a/libgo/go/cmd/go/testdata/script/linkname.txt b/libgo/go/cmd/go/testdata/script/linkname.txt new file mode 100644 index 00000000000..e2ec00c6edc --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/linkname.txt @@ -0,0 +1,7 @@ +# check for linker name in error message about linker crash +[!gc] skip +! go build -ldflags=-crash_for_testing x.go +stderr [\\/]tool[\\/].*[\\/]link + +-- x.go -- +package main; func main() {} diff --git a/libgo/go/cmd/go/testdata/script/list_bad_import.txt b/libgo/go/cmd/go/testdata/script/list_bad_import.txt new file mode 100644 index 00000000000..ba66b0937f8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_bad_import.txt @@ -0,0 +1,67 @@ +# This test matches mod_list_bad_import, but in GOPATH mode. +# Please keep them in sync. + +env GO111MODULE=off +cd example.com + +# Without -e, listing an otherwise-valid package with an unsatisfied direct import should fail. +# BUG: Today it succeeds. +go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}} {{range .DepsErrors}}bad dep: {{.Err}}{{end}}' example.com/direct +! stdout ^error +stdout 'incomplete' +stdout 'bad dep: .*example.com[/\\]notfound' + +# Listing with -deps should also fail. +# BUG: Today, it does not. +# ! go list -deps example.com/direct +# stderr example.com[/\\]notfound +go list -deps example.com/direct +stdout example.com/notfound + + +# Listing an otherwise-valid package that imports some *other* package with an +# unsatisfied import should also fail. +# BUG: Today, it succeeds. +go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}} {{range .DepsErrors}}bad dep: {{.Err}}{{end}}' example.com/indirect +! stdout ^error +stdout incomplete +stdout 'bad dep: .*example.com[/\\]notfound' + +# Again, -deps should fail. +# BUG: Again, it does not. +# ! go list -deps example.com/indirect +# stderr example.com[/\\]notfound +go list -deps example.com/indirect +stdout example.com/notfound + + +# Listing the missing dependency directly should fail outright... +! go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}}' example.com/notfound +stderr 'no Go files in .*example.com[/\\]notfound' +! stdout error +! stdout incomplete + +# ...but listing with -e should succeed. +go list -e -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}}' example.com/notfound +stdout error +stdout incomplete + + +# The pattern "all" should match only packages that acutally exist, +# ignoring those whose existence is merely implied by imports. +go list -e -f '{{.ImportPath}}' all +stdout example.com/direct +stdout example.com/indirect +! stdout example.com/notfound + + +-- example.com/direct/direct.go -- +package direct +import _ "example.com/notfound" + +-- example.com/indirect/indirect.go -- +package indirect +import _ "example.com/direct" + +-- example.com/notfound/README -- +This directory intentionally left blank. diff --git a/libgo/go/cmd/go/testdata/script/list_compiled_imports.txt b/libgo/go/cmd/go/testdata/script/list_compiled_imports.txt new file mode 100644 index 00000000000..2c883b60610 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_compiled_imports.txt @@ -0,0 +1,29 @@ +[!cgo] skip + +# go list should report import "C" +cd x +go list -f '{{.Imports}}' +! stdout runtime/cgo +! stdout unsafe +! stdout syscall +stdout C +stdout unicode +stdout unicode/utf16 + +# go list -compiled should report imports in compiled files as well, +# adding "runtime/cgo", "unsafe", and "syscall" but not dropping "C". +go list -compiled -f '{{.Imports}}' +[!gccgo] stdout runtime/cgo +stdout unsafe +stdout syscall +stdout C +stdout unicode +stdout unicode/utf16 + +-- x/x.go -- +package x +import "C" +import "unicode" // does not use unsafe, syscall, runtime/cgo, unicode/utf16 +-- x/x1.go -- +package x +import "unicode/utf16" // does not use unsafe, syscall, runtime/cgo, unicode diff --git a/libgo/go/cmd/go/testdata/script/list_find.txt b/libgo/go/cmd/go/testdata/script/list_find.txt new file mode 100644 index 00000000000..dbe8fb0ac98 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_find.txt @@ -0,0 +1,10 @@ +# go list -find should not report imports + +go list -f {{.Incomplete}} x/y/z... # should probably exit non-zero but never has +stdout true +go list -find -f '{{.Incomplete}} {{.Imports}}' x/y/z... +stdout '^false \[\]' + +-- x/y/z/z.go -- +package z +import "does/not/exist" diff --git a/libgo/go/cmd/go/testdata/script/list_std.txt b/libgo/go/cmd/go/testdata/script/list_std.txt new file mode 100644 index 00000000000..a63d74db120 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_std.txt @@ -0,0 +1,12 @@ +[!gc] skip + +# listing GOROOT should only find standard packages +cd $GOROOT/src +go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}' ./... +! stdout . +# TODO: ignore _/blah/go/src in output + +# our vendored packages should be reported as standard +go list std cmd +stdout golang_org/x/net/http2/hpack +stdout cmd/vendor/golang\.org/x/arch/x86/x86asm diff --git a/libgo/go/cmd/go/testdata/script/list_tags.txt b/libgo/go/cmd/go/testdata/script/list_tags.txt new file mode 100644 index 00000000000..c5dc99e9fba --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_tags.txt @@ -0,0 +1,8 @@ +# go list supports -tags +go list -tags=thetag ./my... +stdout mypkg + +-- mypkg/x.go -- +// +build thetag + +package mypkg diff --git a/libgo/go/cmd/go/testdata/script/list_test_e.txt b/libgo/go/cmd/go/testdata/script/list_test_e.txt new file mode 100644 index 00000000000..f1473322c65 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_test_e.txt @@ -0,0 +1,9 @@ +# issue 25980: crash in go list -e -test +go list -e -test -f '{{.Error}}' p +stdout '^p[/\\]d_test.go:2:8: cannot find package "d" in any of:' + +-- p/d.go -- +package d +-- p/d_test.go -- +package d_test +import _ "d" diff --git a/libgo/go/cmd/go/testdata/script/list_test_imports.txt b/libgo/go/cmd/go/testdata/script/list_test_imports.txt new file mode 100644 index 00000000000..51d1ce9a696 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/list_test_imports.txt @@ -0,0 +1,19 @@ +# issue 26880: list with tests has wrong variant in imports +go list -test -f '{{.ImportPath}}:{{with .Imports}} {{join . ", "}}{{end}}' a b +cmp stdout imports.txt + +-- a/a.go -- +package a; import _ "b" +-- b/b.go -- +package b +-- b/b_test.go -- +package b +-- b/b_x_test.go -- +package b_test; import _ "a" + +-- imports.txt -- +a: b +b: +b.test: b [b.test], b_test [b.test], os, testing, testing/internal/testdeps +b [b.test]: +b_test [b.test]: a [b.test] diff --git a/libgo/go/cmd/go/testdata/script/mod_bad_domain.txt b/libgo/go/cmd/go/testdata/script/mod_bad_domain.txt new file mode 100644 index 00000000000..c9fd044cdc8 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_bad_domain.txt @@ -0,0 +1,29 @@ +env GO111MODULE=on + +# explicit get should report errors about bad names +! go get appengine +stderr 'malformed module path "appengine": missing dot in first path element' +! go get x/y.z +stderr 'malformed module path "x/y.z": missing dot in first path element' + +# build should report all unsatisfied imports, +# but should be more definitive about non-module import paths +! go build ./useappengine +stderr 'cannot find package' +! go build ./usenonexistent +stderr 'cannot find module providing package nonexistent.rsc.io' + +# go mod vendor and go mod tidy should ignore appengine imports. +rm usenonexistent/x.go +go mod tidy +go mod vendor + +-- go.mod -- +module x + +-- useappengine/x.go -- +package useappengine +import _ "appengine" // package does not exist +-- usenonexistent/x.go -- +package usenonexistent +import _ "nonexistent.rsc.io" // domain does not exist diff --git a/libgo/go/cmd/go/testdata/script/mod_bad_filenames.txt b/libgo/go/cmd/go/testdata/script/mod_bad_filenames.txt new file mode 100644 index 00000000000..6e0c8bd3023 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_bad_filenames.txt @@ -0,0 +1,11 @@ +env GO111MODULE=on + +! go get rsc.io/badfile1 rsc.io/badfile2 rsc.io/badfile3 rsc.io/badfile4 rsc.io/badfile5 +! stderr 'unzip.*badfile1' +stderr 'unzip.*badfile2[\\/]@v[\\/]v1.0.0.zip:.*malformed file path "☺.go": invalid char ''☺''' +stderr 'unzip.*badfile3[\\/]@v[\\/]v1.0.0.zip: malformed file path "x\?y.go": invalid char ''\?''' +stderr 'unzip.*badfile4[\\/]@v[\\/]v1.0.0.zip: case-insensitive file name collision: "x/Y.go" and "x/y.go"' +stderr 'unzip.*badfile5[\\/]@v[\\/]v1.0.0.zip: case-insensitive file name collision: "x/y" and "x/Y"' + +-- go.mod -- +module x diff --git a/libgo/go/cmd/go/testdata/script/mod_build_tags.txt b/libgo/go/cmd/go/testdata/script/mod_build_tags.txt new file mode 100644 index 00000000000..1347eaacbf7 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_build_tags.txt @@ -0,0 +1,30 @@ +# Test that build tags are used. +# golang.org/issue/24053. + +env GO111MODULE=on + +cd x +! go list -f {{.GoFiles}} +stderr 'build constraints exclude all Go files' + +go list -f {{.GoFiles}} -tags tag1 +stdout '\[x.go\]' + +go list -f {{.GoFiles}} -tags tag2 +stdout '\[y\.go\]' + +go list -f {{.GoFiles}} -tags 'tag1 tag2' +stdout '\[x\.go y\.go\]' + +-- x/go.mod -- +module x + +-- x/x.go -- +// +build tag1 + +package y + +-- x/y.go -- +// +build tag2 + +package y diff --git a/libgo/go/cmd/go/testdata/script/mod_case.txt b/libgo/go/cmd/go/testdata/script/mod_case.txt new file mode 100644 index 00000000000..ee818c2c07b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_case.txt @@ -0,0 +1,20 @@ +env GO111MODULE=on + +go get rsc.io/QUOTE +go list -m all +stdout '^rsc.io/quote v1.5.2' +stdout '^rsc.io/QUOTE v1.5.2' + +go list -f 'DIR {{.Dir}} DEPS {{.Deps}}' rsc.io/QUOTE/QUOTE +stdout 'DEPS.*rsc.io/quote' +stdout 'DIR.*!q!u!o!t!e' + +go get rsc.io/QUOTE@v1.5.3-PRE +go list -m all +stdout '^rsc.io/QUOTE v1.5.3-PRE' + +go list -f '{{.Dir}}' rsc.io/QUOTE/QUOTE +stdout '!q!u!o!t!e@v1.5.3-!p!r!e' + +-- go.mod -- +module x diff --git a/libgo/go/cmd/go/testdata/script/mod_case_cgo.txt b/libgo/go/cmd/go/testdata/script/mod_case_cgo.txt new file mode 100644 index 00000000000..917bce92d88 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_case_cgo.txt @@ -0,0 +1,9 @@ +[!cgo] skip + +env GO111MODULE=on + +go get rsc.io/CGO +go build rsc.io/CGO + +-- go.mod -- +module x diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_dep.txt b/libgo/go/cmd/go/testdata/script/mod_convert_dep.txt new file mode 100644 index 00000000000..cc1083bcba2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_convert_dep.txt @@ -0,0 +1,9 @@ +env GO111MODULE=on + +cd $WORK/test/x +go list -m all +stdout '^m$' + +-- $WORK/test/Gopkg.lock -- +-- $WORK/test/x/x.go -- +package x // import "m/x" diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_git.txt b/libgo/go/cmd/go/testdata/script/mod_convert_git.txt new file mode 100644 index 00000000000..5ef534a8f88 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_convert_git.txt @@ -0,0 +1,10 @@ +env GO111MODULE=on + +# detect root of module tree as root of enclosing git repo +cd $WORK/test/x +go list -m all +stdout '^m$' + +-- $WORK/test/.git/config -- +-- $WORK/test/x/x.go -- +package x // import "m/x" diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_glide.txt b/libgo/go/cmd/go/testdata/script/mod_convert_glide.txt new file mode 100644 index 00000000000..50460bbf365 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_convert_glide.txt @@ -0,0 +1,9 @@ +env GO111MODULE=on + +cd $WORK/test/x +go list -m all +stdout '^m$' + +-- $WORK/test/glide.lock -- +-- $WORK/test/x/x.go -- +package x // import "m/x" diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_glockfile.txt b/libgo/go/cmd/go/testdata/script/mod_convert_glockfile.txt new file mode 100644 index 00000000000..4d9aaffab50 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_convert_glockfile.txt @@ -0,0 +1,9 @@ +env GO111MODULE=on + +cd $WORK/test/x +go list -m all +stdout '^m$' + +-- $WORK/test/GLOCKFILE -- +-- $WORK/test/x/x.go -- +package x // import "m/x" diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_godeps.txt b/libgo/go/cmd/go/testdata/script/mod_convert_godeps.txt new file mode 100644 index 00000000000..61fbab11240 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_convert_godeps.txt @@ -0,0 +1,10 @@ +env GO111MODULE=on + +cd $WORK/test/x +go list -m all +stdout '^m$' + +-- $WORK/test/Godeps/Godeps.json -- +{} +-- $WORK/test/x/x.go -- +package x // import "m/x" diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_tsv.txt b/libgo/go/cmd/go/testdata/script/mod_convert_tsv.txt new file mode 100644 index 00000000000..5b82d85d653 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_convert_tsv.txt @@ -0,0 +1,9 @@ +env GO111MODULE=on + +cd $WORK/test/x +go list -m all +stdout '^m$' + +-- $WORK/test/dependencies.tsv -- +-- $WORK/test/x/x.go -- +package x // import "m/x" diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_vendor_conf.txt b/libgo/go/cmd/go/testdata/script/mod_convert_vendor_conf.txt new file mode 100644 index 00000000000..b45d3b69fe2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_convert_vendor_conf.txt @@ -0,0 +1,9 @@ +env GO111MODULE=on + +cd $WORK/test/x +go list -m all +stdout '^m$' + +-- $WORK/test/vendor.conf -- +-- $WORK/test/x/x.go -- +package x // import "m/x" diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_vendor_json.txt b/libgo/go/cmd/go/testdata/script/mod_convert_vendor_json.txt new file mode 100644 index 00000000000..cb6e5fee15f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_convert_vendor_json.txt @@ -0,0 +1,10 @@ +env GO111MODULE=on + +cd $WORK/test/x +go list -m all +stdout '^m$' + +-- $WORK/test/vendor/vendor.json -- +{} +-- $WORK/test/x/x.go -- +package x // import "m/x" diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_vendor_manifest.txt b/libgo/go/cmd/go/testdata/script/mod_convert_vendor_manifest.txt new file mode 100644 index 00000000000..bcf185136ba --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_convert_vendor_manifest.txt @@ -0,0 +1,10 @@ +env GO111MODULE=on + +cd $WORK/test/x +go list -m all +stdout '^m$' + +-- $WORK/test/vendor/manifest -- +{} +-- $WORK/test/x/x.go -- +package x // import "m/x" diff --git a/libgo/go/cmd/go/testdata/script/mod_convert_vendor_yml.txt b/libgo/go/cmd/go/testdata/script/mod_convert_vendor_yml.txt new file mode 100644 index 00000000000..0cd245bace1 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_convert_vendor_yml.txt @@ -0,0 +1,9 @@ +env GO111MODULE=on + +cd $WORK/test/x +go list -m all +stdout '^m$' + +-- $WORK/test/vendor.yml -- +-- $WORK/test/x/x.go -- +package x // import "m/x" diff --git a/libgo/go/cmd/go/testdata/script/mod_doc.txt b/libgo/go/cmd/go/testdata/script/mod_doc.txt new file mode 100644 index 00000000000..450d85754ea --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_doc.txt @@ -0,0 +1,36 @@ +# go doc should find module documentation + +[gccgo] stop 'no go doc' + +env GO111MODULE=on + +go doc y +stdout 'Package y is.*alphabet' +stdout 'import "x/y"' +go doc x/y +stdout 'Package y is.*alphabet' +! go doc quote.Hello +stderr 'doc: symbol quote is not a type' # because quote is not in local cache +go list rsc.io/quote # now it is +go doc quote.Hello +stdout 'Hello returns a greeting' +go doc quote +stdout 'Package quote collects pithy sayings.' + +# Double-check go doc y when y is not in GOPATH/src. +env GOPATH=$WORK/altgopath +go doc x/y +stdout 'Package y is.*alphabet' +go doc y +stdout 'Package y is.*alphabet' + +-- go.mod -- +module x +require rsc.io/quote v1.5.2 + +-- y/y.go -- +// Package y is the next to last package of the alphabet. +package y + +-- x.go -- +package x diff --git a/libgo/go/cmd/go/testdata/script/mod_domain_root.txt b/libgo/go/cmd/go/testdata/script/mod_domain_root.txt new file mode 100644 index 00000000000..e34cc29fa64 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_domain_root.txt @@ -0,0 +1,12 @@ +# Module paths that are domain roots should resolve. +# (example.com not example.com/something) + +env GO111MODULE=on +go build + +-- go.mod -- +module x + +-- x.go -- +package x +import _ "example.com" diff --git a/libgo/go/cmd/go/testdata/script/mod_download.txt b/libgo/go/cmd/go/testdata/script/mod_download.txt new file mode 100644 index 00000000000..6be6acb360c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_download.txt @@ -0,0 +1,64 @@ +env GO111MODULE=on + +# download with version should print nothing +go mod download rsc.io/quote@v1.5.0 +! stdout . + +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.zip + +# download -json with version should print JSON +go mod download -json 'rsc.io/quote@<=v1.5.0' +stdout '^\t"Path": "rsc.io/quote"' +stdout '^\t"Version": "v1.5.0"' +stdout '^\t"Info": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.info"' +stdout '^\t"GoMod": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.mod"' +stdout '^\t"Zip": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.0.zip"' +stdout '^\t"Sum": "h1:6fJa6E\+wGadANKkUMlZ0DhXFpoKlslOQDCo259XtdIE="' # hash of testdata/mod version, not real version! +stdout '^\t"GoModSum": "h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe\+TKr0="' +! stdout '"Error"' + +# download queries above should not have added to go.mod. +go list -m all +! stdout rsc.io + +# add to go.mod so we can test non-query downloads +go mod edit -require rsc.io/quote@v1.5.2 +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip + +# module loading will page in the info and mod files +go list -m all +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip + +# download will fetch and unpack the zip file +go mod download +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.info +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.mod +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.2.zip +exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 + +go mod download -json +stdout '^\t"Path": "rsc.io/quote"' +stdout '^\t"Version": "v1.5.2"' +stdout '^\t"Info": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.2.info"' +stdout '^\t"GoMod": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.2.mod"' +stdout '^\t"Zip": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)cache(\\\\|/)download(\\\\|/)rsc.io(\\\\|/)quote(\\\\|/)@v(\\\\|/)v1.5.2.zip"' +stdout '^\t"Dir": ".*(\\\\|/)pkg(\\\\|/)mod(\\\\|/)rsc.io(\\\\|/)quote@v1.5.2"' + +# download will follow replacements +go mod edit -require rsc.io/quote@v1.5.1 -replace rsc.io/quote@v1.5.1=rsc.io/quote@v1.5.3-pre1 +go mod download +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.zip +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.3-pre1.zip + +# download will not follow replacements for explicit module queries +go mod download -json rsc.io/quote@v1.5.1 +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.1.zip + +-- go.mod -- +module m diff --git a/libgo/go/cmd/go/testdata/script/mod_edit.txt b/libgo/go/cmd/go/testdata/script/mod_edit.txt new file mode 100644 index 00000000000..60a6f745361 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_edit.txt @@ -0,0 +1,136 @@ +env GO111MODULE=on + +# Test that go mod edits and related mod flags work. +# Also test that they can use a dummy name that isn't resolvable. golang.org/issue/24100 + +# go mod init +! go mod init +stderr 'cannot determine module path' +! exists go.mod + +go mod init x.x/y/z +stderr 'creating new go.mod: module x.x/y/z' +cmp go.mod $WORK/go.mod.init + +! go mod init +cmp go.mod $WORK/go.mod.init + +# go mod edits +go mod edit -droprequire=x.1 -require=x.1@v1.0.0 -require=x.2@v1.1.0 -droprequire=x.2 -exclude='x.1 @ v1.2.0' -exclude=x.1@v1.2.1 -replace=x.1@v1.3.0=y.1@v1.4.0 -replace='x.1@v1.4.0 = ../z' +cmp go.mod $WORK/go.mod.edit1 +go mod edit -droprequire=x.1 -dropexclude=x.1@v1.2.1 -dropreplace=x.1@v1.3.0 -require=x.3@v1.99.0 +cmp go.mod $WORK/go.mod.edit2 + +# go mod edit -json +go mod edit -json +cmp stdout $WORK/go.mod.json + +# go mod edit -replace +go mod edit -replace=x.1@v1.3.0=y.1/v2@v2.3.5 -replace=x.1@v1.4.0=y.1/v2@v2.3.5 +cmp go.mod $WORK/go.mod.edit3 +go mod edit -replace=x.1=y.1/v2@v2.3.6 +cmp go.mod $WORK/go.mod.edit4 +go mod edit -dropreplace=x.1 +cmp go.mod $WORK/go.mod.edit5 + +# go mod edit -fmt +cp $WORK/go.mod.badfmt go.mod +go mod edit -fmt -print # -print should avoid writing file +cmp stdout $WORK/go.mod.edit4 +cmp go.mod $WORK/go.mod.badfmt +go mod edit -fmt # without -print, should write file (and nothing to stdout) +! stdout . +cmp go.mod $WORK/go.mod.edit4 + +-- x.go -- +package x + +-- w/w.go -- +package w + +-- $WORK/go.mod.init -- +module x.x/y/z +-- $WORK/go.mod.edit1 -- +module x.x/y/z + +require x.1 v1.0.0 + +exclude ( + x.1 v1.2.0 + x.1 v1.2.1 +) + +replace ( + x.1 v1.3.0 => y.1 v1.4.0 + x.1 v1.4.0 => ../z +) +-- $WORK/go.mod.edit2 -- +module x.x/y/z + +exclude x.1 v1.2.0 + +replace x.1 v1.4.0 => ../z + +require x.3 v1.99.0 +-- $WORK/go.mod.json -- +{ + "Module": { + "Path": "x.x/y/z" + }, + "Require": [ + { + "Path": "x.3", + "Version": "v1.99.0" + } + ], + "Exclude": [ + { + "Path": "x.1", + "Version": "v1.2.0" + } + ], + "Replace": [ + { + "Old": { + "Path": "x.1", + "Version": "v1.4.0" + }, + "New": { + "Path": "../z" + } + } + ] +} +-- $WORK/go.mod.edit3 -- +module x.x/y/z + +exclude x.1 v1.2.0 + +replace ( + x.1 v1.3.0 => y.1/v2 v2.3.5 + x.1 v1.4.0 => y.1/v2 v2.3.5 +) + +require x.3 v1.99.0 +-- $WORK/go.mod.edit4 -- +module x.x/y/z + +exclude x.1 v1.2.0 + +replace x.1 => y.1/v2 v2.3.6 + +require x.3 v1.99.0 +-- $WORK/go.mod.edit5 -- +module x.x/y/z + +exclude x.1 v1.2.0 + +require x.3 v1.99.0 +-- $WORK/go.mod.badfmt -- +module x.x/y/z + +exclude x.1 v1.2.0 + +replace x.1 => y.1/v2 v2.3.6 + +require x.3 v1.99.0 diff --git a/libgo/go/cmd/go/testdata/script/mod_enabled.txt b/libgo/go/cmd/go/testdata/script/mod_enabled.txt new file mode 100644 index 00000000000..8eef870b02b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_enabled.txt @@ -0,0 +1,82 @@ +# GO111MODULE=auto should only trigger outside GOPATH/src +env GO111MODULE=auto + +cd $GOPATH/src/x/y/z +go env GOMOD +! stdout . # no non-empty lines +! go list -m -f {{.GoMod}} +stderr 'not using modules' + +cd $GOPATH/src/x/y/z/w +go env GOMOD +! stdout . + +cd $GOPATH/src/x/y +go env GOMOD +! stdout . + +cd $GOPATH/foo +go env GOMOD +stdout foo[/\\]go.mod +go list -m -f {{.GoMod}} +stdout foo[/\\]go.mod + +cd $GOPATH/foo/bar/baz +go env GOMOD +stdout foo[/\\]go.mod + +# GO111MODULE=on should trigger everywhere +env GO111MODULE=on + +cd $GOPATH/src/x/y/z +go env GOMOD +stdout z[/\\]go.mod + +cd $GOPATH/src/x/y/z/w +go env GOMOD +stdout z[/\\]go.mod + +cd $GOPATH/src/x/y +go env GOMOD +! stdout . +! go list -m +stderr 'cannot find main module' + +cd $GOPATH/foo +go env GOMOD +stdout foo[/\\]go.mod + +cd $GOPATH/foo/bar/baz +go env GOMOD +stdout foo[/\\]go.mod + +# GO111MODULE=off should trigger nowhere +env GO111MODULE=off + +cd $GOPATH/src/x/y/z +go env GOMOD +! stdout .+ + +cd $GOPATH/foo +go env GOMOD +! stdout .+ + +cd $GOPATH/foo/bar/baz +go env GOMOD +! stdout .+ + +# GO111MODULE=auto should ignore and warn about /tmp/go.mod +env GO111MODULE=auto +cp $GOPATH/src/x/y/z/go.mod $WORK/tmp/go.mod +mkdir $WORK/tmp/mydir +cd $WORK/tmp/mydir +go env GOMOD +! stdout .+ +stderr '^go: warning: ignoring go.mod in system temp root ' + +-- $GOPATH/src/x/y/z/go.mod -- +module x/y/z +-- $GOPATH/src/x/y/z/w/w.txt -- +-- $GOPATH/foo/go.mod -- +module example.com/mod +-- $GOPATH/foo/bar/baz/quux.txt -- diff --git a/libgo/go/cmd/go/testdata/script/mod_file_proxy.txt b/libgo/go/cmd/go/testdata/script/mod_file_proxy.txt new file mode 100644 index 00000000000..8de6d7dbb88 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_file_proxy.txt @@ -0,0 +1,25 @@ +# Allow (cached) downloads for -mod=readonly. +env GO111MODULE=on +env GOPATH=$WORK/gopath1 +cd $WORK/x +go mod edit -fmt +go list -mod=readonly +env GOPROXY=file:///nonexist +go list +grep v1.5.1 $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/list + +# Use download cache as file:/// proxy. +[windows] stop # TODO: file://$WORK puts backslashes in the URL +env GOPATH=$WORK/gopath2 +env GOPROXY=file:///nonexist +! go list +env GOPROXY=file://$WORK/gopath1/pkg/mod/cache/download +go list +grep v1.5.1 $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/list + +-- $WORK/x/go.mod -- +module x +require rsc.io/quote v1.5.1 +-- $WORK/x/x.go -- +package x +import _ "rsc.io/quote" diff --git a/libgo/go/cmd/go/testdata/script/mod_find.txt b/libgo/go/cmd/go/testdata/script/mod_find.txt new file mode 100644 index 00000000000..f4ac8d01f56 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_find.txt @@ -0,0 +1,91 @@ +# Derive module path from import comment. +cd $WORK/x +exists x.go +go mod init +stderr 'module x' + +# Import comment works even with CRLF line endings. +rm go.mod +addcrlf x.go +go mod init +stderr 'module x' + +# go mod should die in GOPATH if modules are not enabled for GOPATH +cd $GOPATH/src/example.com/x/y +! go mod init +stderr 'go: modules disabled inside GOPATH/src by GO111MODULE=auto; see ''go help modules''' + +env GO111MODULE=on + +# Derive module path from location inside GOPATH. +cd $GOPATH/src/example.com/x/y +go mod init +stderr 'module example.com/x/y$' +rm go.mod + +# Module path from Godeps/Godeps.json overrides GOPATH. +cd $GOPATH/src/example.com/x/y/z +go mod init +stderr 'unexpected.com/z' +rm go.mod + +# Empty directory outside GOPATH fails. +mkdir $WORK/empty +cd $WORK/empty +! go mod init +stderr 'cannot determine module path for source directory' +rm go.mod + +# Empty directory inside GOPATH/src uses location inside GOPATH. +mkdir $GOPATH/src/empty +cd $GOPATH/src/empty +go mod init +stderr 'empty' +rm go.mod + +[!symlink] stop + +# gplink1/src/empty where gopathlink -> GOPATH +symlink $WORK/gopathlink -> gopath +cd $WORK/gopathlink/src/empty +go mod init +rm go.mod + +# GOPATH/src/link where link -> out of GOPATH +symlink $GOPATH/src/link -> $WORK/empty +cd $WORK/empty +! go mod init +cd $GOPATH/src/link +go mod init +stderr link +rm go.mod + +# GOPATH/src/empty where GOPATH itself is a symlink +env GOPATH=$WORK/gopathlink +cd $GOPATH/src/empty +go mod init +rm go.mod +cd $WORK/gopath/src/empty +go mod init +rm go.mod + +# GOPATH/src/link where GOPATH and link are both symlinks +cd $GOPATH/src/link +go mod init +stderr link +rm go.mod + +# Too hard: doesn't match unevaluated nor completely evaluated. (Only partially evaluated.) +# Whether this works depends on which OS we are running on. +# cd $WORK/gopath/src/link +# ! go mod init + +-- $WORK/x/x.go -- +package x // import "x" + +-- $GOPATH/src/example.com/x/y/y.go -- +package y +-- $GOPATH/src/example.com/x/y/z/z.go -- +package z +-- $GOPATH/src/example.com/x/y/z/Godeps/Godeps.json -- +{"ImportPath": "unexpected.com/z"} diff --git a/libgo/go/cmd/go/testdata/script/mod_fs_patterns.txt b/libgo/go/cmd/go/testdata/script/mod_fs_patterns.txt new file mode 100644 index 00000000000..d7d3e0321b5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_fs_patterns.txt @@ -0,0 +1,66 @@ +# File system pattern searches should skip sub-modules and vendor directories. + +env GO111MODULE=on + +cd x + +# all packages +go list all +stdout ^m$ +stdout ^m/vendor$ +! stdout vendor/ +stdout ^m/y$ +! stdout ^m/y/z + +# path pattern +go list m/... +stdout ^m$ +stdout ^m/vendor$ +! stdout vendor/ +stdout ^m/y$ +! stdout ^m/y/z + +# directory pattern +go list ./... +stdout ^m$ +stdout ^m/vendor$ +! stdout vendor/ +stdout ^m/y$ +! stdout ^m/y/z + +# non-existent directory should not prompt lookups +! go build -mod=readonly example.com/nonexist +stderr 'import lookup disabled' + +! go build -mod=readonly ./nonexist +! stderr 'import lookup disabled' +stderr '^go: no such directory ./nonexist' + +! go build -mod=readonly ./go.mod +! stderr 'import lookup disabled' +stderr '^go: ./go.mod is not a directory' + +-- x/go.mod -- +module m + +-- x/x.go -- +package x + +-- x/vendor/v/v.go -- +package v +import _ "golang.org/x/crypto" + +-- x/vendor/v.go -- +package main + +-- x/y/y.go -- +package y + +-- x/y/z/go.mod -- +syntax error! + +-- x/y/z/z.go -- +package z + +-- x/y/z/w/w.go -- +package w diff --git a/libgo/go/cmd/go/testdata/script/mod_get_commit.txt b/libgo/go/cmd/go/testdata/script/mod_get_commit.txt new file mode 100644 index 00000000000..589a791fd4d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_commit.txt @@ -0,0 +1,53 @@ +env GO111MODULE=on + +# @commit should resolve + +# golang.org/x/text/language@commit should not resolve with -m, +# because that's not a module path. +! go get -m golang.org/x/text/language@14c0d48 + +# ... but it should work without -m. +# because of -d, the compiler should not run +go get -d -x golang.org/x/text/language@14c0d48 +! stderr 'compile|cp|gccgo .*language\.a$' + +# go get should skip build with no Go files in root +go get golang.org/x/text@14c0d48 + +# ... and go get should skip build with -m +go get -m golang.org/x/text@14c0d48 + +# dropping -d, we should see a build. +go get -x golang.org/x/text/language@14c0d48 +stderr 'compile|cp|gccgo .*language\.a$' + +# BUG: after the build, the package should not be stale, as 'go install' would +# not do anything further. +go list -f '{{.Stale}}' golang.org/x/text/language +stdout ^true + +# install after get should not run the compiler again. +go install -x golang.org/x/text/language +! stderr 'compile|cp|gccgo .*language\.a$' + +# even with -d, we should see an error for unknown packages. +! go get -d -x golang.org/x/text/foo@14c0d48 + +# get pseudo-version should record that version +go get rsc.io/quote@v0.0.0-20180214005840-23179ee8a569 +grep 'rsc.io/quote v0.0.0-20180214005840-23179ee8a569' go.mod + +# but as commit should record as v1.5.1 +go get rsc.io/quote@23179ee8 +grep 'rsc.io/quote v1.5.1' go.mod + +# go mod edit -require does not interpret commits +go mod edit -require rsc.io/quote@23179ee +grep 'rsc.io/quote 23179ee' go.mod + +# but other commands fix them +go mod graph +grep 'rsc.io/quote v1.5.1' go.mod + +-- go.mod -- +module x diff --git a/libgo/go/cmd/go/testdata/script/mod_get_downgrade.txt b/libgo/go/cmd/go/testdata/script/mod_get_downgrade.txt new file mode 100644 index 00000000000..ac814dae08f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_downgrade.txt @@ -0,0 +1,39 @@ +env GO111MODULE=on + +# downgrade sampler should downgrade quote +go get rsc.io/sampler@v1.0.0 +go list -m all +stdout 'rsc.io/quote v1.4.0' +stdout 'rsc.io/sampler v1.0.0' + +# downgrade sampler away should downgrade quote further +go get rsc.io/sampler@none +go list -m all +stdout 'rsc.io/quote v1.3.0' + +# downgrade should report inconsistencies and not change go.mod +go get rsc.io/quote@v1.5.1 +go list -m all +stdout 'rsc.io/quote v1.5.1' +stdout 'rsc.io/sampler v1.3.0' +! go get rsc.io/sampler@v1.0.0 rsc.io/quote@v1.5.2 golang.org/x/text@none +stderr 'go get: inconsistent versions:\n\trsc.io/quote@v1.5.2 requires golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c \(not golang.org/x/text@none\), rsc.io/sampler@v1.3.0 \(not rsc.io/sampler@v1.0.0\)' +go list -m all +stdout 'rsc.io/quote v1.5.1' +stdout 'rsc.io/sampler v1.3.0' + +# go get -u args should limit upgrades +cp go.mod.empty go.mod +go get -u rsc.io/quote@v1.4.0 rsc.io/sampler@v1.0.0 +go list -m all +stdout 'rsc.io/quote v1.4.0' +stdout 'rsc.io/sampler v1.0.0' +! stdout golang.org/x/text + +-- go.mod -- +module x +require rsc.io/quote v1.5.1 +-- go.mod.empty -- +module x +-- x.go -- +package x diff --git a/libgo/go/cmd/go/testdata/script/mod_get_incompatible.txt b/libgo/go/cmd/go/testdata/script/mod_get_incompatible.txt new file mode 100644 index 00000000000..b210715a5de --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_incompatible.txt @@ -0,0 +1,26 @@ +env GO111MODULE=on + +go list x +go list -m all +stdout 'rsc.io/breaker v2.0.0\+incompatible' + +cp go.mod2 go.mod +go get rsc.io/breaker@7307b30 +go list -m all +stdout 'rsc.io/breaker v2.0.0\+incompatible' + +go get rsc.io/breaker@v2.0.0 +go list -m all +stdout 'rsc.io/breaker v2.0.0\+incompatible' + +-- go.mod -- +module x + +-- go.mod2 -- +module x +require rsc.io/breaker v1.0.0 + +-- x.go -- +package x +import "rsc.io/breaker" +var _ = breaker.XX diff --git a/libgo/go/cmd/go/testdata/script/mod_get_indirect.txt b/libgo/go/cmd/go/testdata/script/mod_get_indirect.txt new file mode 100644 index 00000000000..3ae5833834b --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_indirect.txt @@ -0,0 +1,51 @@ +env GO111MODULE=on + +# get -u should find quote v1.5.2 +go get -u +go list -m all +stdout 'quote v1.5.2$' +grep 'rsc.io/quote v1.5.2$' go.mod + +# it should also update x/text later than requested by v1.5.2 +go list -m -f '{{.Path}} {{.Version}}{{if .Indirect}} // indirect{{end}}' all +stdout '^golang.org/x/text [v0-9a-f\.-]+ // indirect' +grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod + +# importing an empty module root as a package makes it direct. +# TODO(bcmills): This doesn't seem correct. Fix is in the next change. +cp $WORK/tmp/usetext.go x.go +go list -e +grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod + +# indirect tag should be removed upon seeing direct import. +cp $WORK/tmp/uselang.go x.go +go list +grep 'rsc.io/quote v1.5.2$' go.mod +grep 'golang.org/x/text [v0-9a-f\.-]+$' go.mod + +# indirect tag should be added by go mod tidy +cp $WORK/tmp/usequote.go x.go +go mod tidy +grep 'rsc.io/quote v1.5.2$' go.mod +grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod + +# requirement should be dropped entirely if not needed +cp $WORK/tmp/uselang.go x.go +go mod tidy +! grep rsc.io/quote go.mod +grep 'golang.org/x/text [v0-9a-f\.-]+$' go.mod + +-- go.mod -- +module x +require rsc.io/quote v1.5.1 +-- x.go -- +package x +-- $WORK/tmp/usetext.go -- +package x +import _ "golang.org/x/text" +-- $WORK/tmp/uselang.go -- +package x +import _ "golang.org/x/text/language" +-- $WORK/tmp/usequote.go -- +package x +import _ "rsc.io/quote" diff --git a/libgo/go/cmd/go/testdata/script/mod_get_local.txt b/libgo/go/cmd/go/testdata/script/mod_get_local.txt new file mode 100644 index 00000000000..4edda993f1e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_local.txt @@ -0,0 +1,61 @@ +# Test 'go get' with a local module with a name that is not valid for network lookup. + +env GO111MODULE=on +go mod edit -fmt +cp go.mod go.mod.orig + +# 'go get -u -m' within the main module should work, even if it has a local-only name. +cp go.mod.orig go.mod +go get -u -m +grep 'rsc.io/quote.*v1.5.2' go.mod +grep 'golang.org/x/text.*v0.3.0' go.mod +cp go.mod go.mod.implicitmod + +# 'go get -u -m' with the name of the main module should be equivalent to +# 'go get -u -m' without any further arguments. +cp go.mod.orig go.mod +go get -u -m local +cmp go.mod go.mod.implicitmod + +# 'go get -u -d' in the empty root of the main module should update the +# dependencies of all packages in the module. +cp go.mod.orig go.mod +go get -u -d +cmp go.mod go.mod.implicitmod + +# 'go get -u -d .' within a package in the main module updates all dependencies +# of the main module. +# TODO: Determine whether that behavior is a bug. +# (https://golang.org/issue/26902) +cp go.mod.orig go.mod +cd uselang +go get -u -d . +cd .. +grep 'rsc.io/quote.*v1.5.2' go.mod +grep 'golang.org/x/text.*v0.3.0' go.mod +cp go.mod go.mod.dotpkg + +# 'go get -u -d' with an explicit package in the main module updates +# all dependencies of the main module. +# TODO: Determine whether that behavior is a bug. +# (https://golang.org/issue/26902) +cp go.mod.orig go.mod +go get -u -d local/uselang +cmp go.mod go.mod.dotpkg + + +-- go.mod -- +module local + +require ( + golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c + rsc.io/quote v1.3.0 +) + +-- uselang/uselang.go -- +package uselang +import _ "golang.org/x/text/language" + +-- usequote/usequote.go -- +package usequote +import _ "rsc.io/quote" diff --git a/libgo/go/cmd/go/testdata/script/mod_get_moved.txt b/libgo/go/cmd/go/testdata/script/mod_get_moved.txt new file mode 100644 index 00000000000..be914491552 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_moved.txt @@ -0,0 +1,37 @@ +env GO111MODULE=on + +# A 'go get' that worked at a previous version should continue to work at that version, +# even if the package was subsequently moved into a submodule. +go mod init example.com/foo +go get -d example.com/split/subpkg@v1.0.0 +go list -m all +stdout 'example.com/split v1.0.0' + +# A 'go get' that simultaneously upgrades away conflicting package defitions is not ambiguous. +go get example.com/split/subpkg@v1.1.0 + +# A 'go get' without an upgrade should find the package. +rm go.mod +go mod init example.com/foo +go get -d example.com/split/subpkg +go list -m all +stdout 'example.com/split/subpkg v1.1.0' + + +# A 'go get' that worked at a previous version should continue to work at that version, +# even if the package was subsequently moved into a parent module. +rm go.mod +go mod init example.com/foo +go get -d example.com/join/subpkg@v1.0.0 +go list -m all +stdout 'example.com/join/subpkg v1.0.0' + +# A 'go get' that simultaneously upgrades away conflicting package definitions is not ambiguous. +go get example.com/join/subpkg@v1.1.0 + +# A 'go get' without an upgrade should find the package. +rm go.mod +go mod init example.com/foo +go get -d example.com/join/subpkg@v1.1.0 +go list -m all +stdout 'example.com/join v1.1.0' diff --git a/libgo/go/cmd/go/testdata/script/mod_get_none.txt b/libgo/go/cmd/go/testdata/script/mod_get_none.txt new file mode 100644 index 00000000000..5aec209f59f --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_none.txt @@ -0,0 +1,12 @@ +env GO111MODULE=on + +go mod init example.com/foo + +# 'go get bar@none' should be a no-op if module bar is not active. +go get example.com/bar@none +go list -m all +! stdout example.com/bar + +go get example.com/bar@none +go list -m all +! stdout example.com/bar diff --git a/libgo/go/cmd/go/testdata/script/mod_get_pseudo.txt b/libgo/go/cmd/go/testdata/script/mod_get_pseudo.txt new file mode 100644 index 00000000000..3945fdfa893 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_pseudo.txt @@ -0,0 +1,80 @@ +env GO111MODULE=on + +# Testing git->module converter's generation of +incompatible tags; turn off proxy. +[!net] skip +[!exec:git] skip +env GOPROXY= + +# We can resolve the @master branch without unshallowing the local repository +# (even with older gits), so try that before we do anything else. +# (This replicates https://golang.org/issue/26713 with git 2.7.4.) +go get -m github.com/rsc/legacytest@master +go list -m all +stdout '^github.com/rsc/legacytest v2\.0\.1-0\.\d{14}-7303f7796364\+incompatible$' + +# get should include incompatible tags in "latest" calculation. +go get -m github.com/rsc/legacytest@latest +go list +go list -m all +stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$' + +# v2.0.1-0.pseudo+incompatible +go get -m ...test@7303f77 +go list -m all +stdout '^github.com/rsc/legacytest v2\.0\.1-0\.\d{14}-7303f7796364\+incompatible$' + +# v2.0.0+incompatible by tag+incompatible +go get -m ...test@v2.0.0+incompatible +go list -m all +stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$' + +# v2.0.0+incompatible by tag +go get -m ...test@v2.0.0 +go list -m all +stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$' + +# v2.0.0+incompatible by hash (back on master) +go get -m ...test@d7ae1e4 +go list -m all +stdout '^github.com/rsc/legacytest v2\.0\.0\+incompatible$' + +# v1.2.1-0.pseudo +go get -m ...test@d2d4c3e +go list -m all +stdout '^github.com/rsc/legacytest v1\.2\.1-0\.\d{14}-d2d4c3ea6623$' + +# v1.2.0 +go get -m ...test@9f6f860 +go list -m all +stdout '^github.com/rsc/legacytest v1\.2\.0$' + +# v1.1.0-pre.0.pseudo +go get -m ...test@fb3c628 +go list -m all +stdout '^github.com/rsc/legacytest v1\.1\.0-pre\.0\.\d{14}-fb3c628075e3$' + +# v1.1.0-pre (no longer on master) +go get -m ...test@731e3b1 +go list -m all +stdout '^github.com/rsc/legacytest v1\.1\.0-pre$' + +# v1.0.1-0.pseudo +go get -m ...test@fa4f5d6 +go list -m all +stdout '^github.com/rsc/legacytest v1\.0\.1-0\.\d{14}-fa4f5d6a71c6$' + +# v1.0.0 +go get -m ...test@7fff7f3 +go list -m all +stdout '^github.com/rsc/legacytest v1\.0\.0$' + +# v0.0.0-pseudo +go get -m ...test@52853eb +go list -m all +stdout '^github.com/rsc/legacytest v0\.0\.0-\d{14}-52853eb7b552$' + +-- go.mod -- +module x +-- x.go -- +package x +import "github.com/rsc/legacytest" diff --git a/libgo/go/cmd/go/testdata/script/mod_get_upgrade.txt b/libgo/go/cmd/go/testdata/script/mod_get_upgrade.txt new file mode 100644 index 00000000000..5eb5ff96577 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_upgrade.txt @@ -0,0 +1,41 @@ +env GO111MODULE=on + +go get rsc.io/quote@v1.5.1 +go list -m all +stdout 'rsc.io/quote v1.5.1' +grep 'rsc.io/quote v1.5.1$' go.mod + +# get -u should update all dependencies +go get -u +grep 'rsc.io/quote v1.5.2$' go.mod +grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod + +# get -u rsc.io/sampler should update only sampler's dependencies +cp go.mod-v1.5.1 go.mod +go get -u rsc.io/sampler +grep 'rsc.io/quote v1.5.1$' go.mod +grep 'golang.org/x/text [v0-9a-f\.-]+ // indirect' go.mod + +# move to a pseudo-version after any tags +go get -m rsc.io/quote@dd9747d +grep 'rsc.io/quote v0.0.0-20180628003336-dd9747d19b04' go.mod + +# get -u should not jump off newer pseudo-version to earlier tag +go get -m -u +grep 'rsc.io/quote v0.0.0-20180628003336-dd9747d19b04' go.mod + +# move to earlier pseudo-version +go get -m rsc.io/quote@e7a685a342 +grep 'rsc.io/quote v0.0.0-20180214005133-e7a685a342c0' go.mod + +# get -u should jump off earlier pseudo-version to newer tag +go get -m -u +grep 'rsc.io/quote v1.5.2' go.mod + +-- go.mod -- +module x +require rsc.io/quote v1.1.0 + +-- go.mod-v1.5.1 -- +module x +require rsc.io/quote v1.5.1 diff --git a/libgo/go/cmd/go/testdata/script/mod_get_warning.txt b/libgo/go/cmd/go/testdata/script/mod_get_warning.txt new file mode 100644 index 00000000000..36b5434c3ba --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_get_warning.txt @@ -0,0 +1,10 @@ +# go get in GO111MODULE=auto should warn when not using modules and go.mod exists + +env GO111MODULE=auto +mkdir z +cd z +! go get # fails because no code in directory, not the warning +stderr 'go get: warning: modules disabled by GO111MODULE=auto in GOPATH/src;\n\tignoring ..[/\\]go.mod;\n\tsee ''go help modules''' + +-- go.mod -- +module x diff --git a/libgo/go/cmd/go/testdata/script/mod_getmode_vendor.txt b/libgo/go/cmd/go/testdata/script/mod_getmode_vendor.txt new file mode 100644 index 00000000000..3dd8d1b888d --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_getmode_vendor.txt @@ -0,0 +1,23 @@ +env GO111MODULE=on + +go get -m rsc.io/quote@v1.5.1 +go mod vendor +env GOPATH=$WORK/empty +env GOPROXY=file:///nonexist + +go list -mod=vendor +go list -mod=vendor -m -f '{{.Path}} {{.Version}} {{.Dir}}' all +stdout '^rsc.io/quote v1.5.1 .*vendor[\\/]rsc.io[\\/]quote$' +stdout '^golang.org/x/text v0.0.0.* .*vendor[\\/]golang.org[\\/]x[\\/]text$' + +! go list -mod=vendor -m rsc.io/quote@latest +stderr 'module lookup disabled by -mod=vendor' +! go get -mod=vendor -u +stderr 'go get: disabled by -mod=vendor' + +-- go.mod -- +module x + +-- x.go -- +package x +import _ "rsc.io/quote" diff --git a/libgo/go/cmd/go/testdata/script/mod_go_version.txt b/libgo/go/cmd/go/testdata/script/mod_go_version.txt new file mode 100644 index 00000000000..f2de74cee87 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_go_version.txt @@ -0,0 +1,61 @@ +# Test support for declaring needed Go version in module. + +env GO111MODULE=on + +go list +! go build +stderr 'module requires Go 1.999' +go build sub.1 +! go build badsub.1 +stderr 'module requires Go 1.11111' + +go build versioned.1 +go mod edit -require versioned.1@v1.1.0 +! go build versioned.1 +stderr 'module requires Go 1.99999' + +-- go.mod -- +module m +go 1.999 +require ( + sub.1 v1.0.0 + badsub.1 v1.0.0 + versioned.1 v1.0.0 +) +replace ( + sub.1 => ./sub + badsub.1 => ./badsub + versioned.1 v1.0.0 => ./versioned1 + versioned.1 v1.1.0 => ./versioned2 +) + +-- x.go -- +package x + +-- sub/go.mod -- +module m +go 1.11 + +-- sub/x.go -- +package x + +-- badsub/go.mod -- +module m +go 1.11111 + +-- badsub/x.go -- +package x + +-- versioned1/go.mod -- +module versioned +go 1.0 + +-- versioned1/x.go -- +package x + +-- versioned2/go.mod -- +module versioned +go 1.99999 + +-- versioned2/x.go -- +package x diff --git a/libgo/go/cmd/go/testdata/script/mod_gobuild_import.txt b/libgo/go/cmd/go/testdata/script/mod_gobuild_import.txt new file mode 100644 index 00000000000..932b8b66f92 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_gobuild_import.txt @@ -0,0 +1,74 @@ +# go/build's Import should find modules by invoking the go command + +go build -o $WORK/testimport.exe ./testimport + +# GO111MODULE=off +env GO111MODULE=off +! exec $WORK/testimport.exe x/y/z/w . + +# GO111MODULE=auto in GOPATH/src +env GO111MODULE= +! exec $WORK/testimport.exe x/y/z/w . +env GO111MODULE=auto +! exec $WORK/testimport.exe x/y/z/w . + +# GO111MODULE=auto outside GOPATH/src +cd $GOPATH/other +env GO111MODULE= +exec $WORK/testimport.exe other/x/y/z/w . +stdout w2.go + +! exec $WORK/testimport.exe x/y/z/w . +stderr 'cannot find module providing package x/y/z/w' + +cd z +env GO111MODULE=auto +exec $WORK/testimport.exe other/x/y/z/w . +stdout w2.go + +# GO111MODULE=on outside GOPATH/src +env GO111MODULE=on +exec $WORK/testimport.exe other/x/y/z/w . +stdout w2.go + +# GO111MODULE=on in GOPATH/src +cd $GOPATH/src +exec $WORK/testimport.exe x/y/z/w . +stdout w1.go +cd w +exec $WORK/testimport.exe x/y/z/w .. +stdout w1.go + +-- go.mod -- +module x/y/z + +-- z.go -- +package z + +-- w/w1.go -- +package w + +-- testimport/x.go -- +package main + +import ( + "fmt" + "go/build" + "log" + "os" + "strings" +) + +func main() { + p, err := build.Import(os.Args[1], os.Args[2], 0) + if err != nil { + log.Fatal(err) + } + fmt.Printf("%s\n%s\n", p.Dir, strings.Join(p.GoFiles, " ")) +} + +-- $GOPATH/other/go.mod -- +module other/x/y + +-- $GOPATH/other/z/w/w2.go -- +package w diff --git a/libgo/go/cmd/go/testdata/script/mod_gofmt_invalid.txt b/libgo/go/cmd/go/testdata/script/mod_gofmt_invalid.txt new file mode 100644 index 00000000000..21edc7dc2f4 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_gofmt_invalid.txt @@ -0,0 +1,13 @@ +# Test for a crash in go fmt on invalid input when using modules. +# Issue 26792. + +env GO111MODULE=on +! go fmt x.go +! stderr panic + +-- go.mod -- +module x + +-- x.go -- +// Missing package declaration. +var V int diff --git a/libgo/go/cmd/go/testdata/script/mod_gopkg_unstable.txt b/libgo/go/cmd/go/testdata/script/mod_gopkg_unstable.txt new file mode 100644 index 00000000000..d945cf35b43 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_gopkg_unstable.txt @@ -0,0 +1,22 @@ +env GO111MODULE=on + +cp go.mod.empty go.mod +go get -d gopkg.in/dummy.v2-unstable + +cp x.go.txt x.go +cp go.mod.empty go.mod +go list + +[!net] skip + +env GOPROXY= +go get gopkg.in/macaroon-bakery.v2-unstable/bakery +go list -m all +stdout 'gopkg.in/macaroon-bakery.v2-unstable v2.0.0-[0-9]+-[0-9a-f]+$' + +-- go.mod.empty -- +module m + +-- x.go.txt -- +package x +import _ "gopkg.in/dummy.v2-unstable" diff --git a/libgo/go/cmd/go/testdata/script/mod_graph.txt b/libgo/go/cmd/go/testdata/script/mod_graph.txt new file mode 100644 index 00000000000..07968f531d2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_graph.txt @@ -0,0 +1,10 @@ +env GO111MODULE=on + +go mod graph +stdout '^m rsc.io/quote@v1.5.2$' +stdout '^rsc.io/quote@v1.5.2 rsc.io/sampler@v1.3.0$' +! stdout '^m rsc.io/sampler@v1.3.0$' + +-- go.mod -- +module m +require rsc.io/quote v1.5.2 diff --git a/libgo/go/cmd/go/testdata/script/mod_import.txt b/libgo/go/cmd/go/testdata/script/mod_import.txt new file mode 100644 index 00000000000..3985b43144c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_import.txt @@ -0,0 +1,18 @@ +env GO111MODULE=on + +# latest rsc.io/quote should be v1.5.2 not v1.5.3-pre1 +go list +go list -m all +stdout 'rsc.io/quote v1.5.2' + +# but v1.5.3-pre1 should be a known version +go list -m -versions rsc.io/quote +stdout '^rsc.io/quote v1.0.0 v1.1.0 v1.2.0 v1.2.1 v1.3.0 v1.4.0 v1.5.0 v1.5.1 v1.5.2 v1.5.3-pre1$' + +-- go.mod -- +module x + +-- x.go -- +package x +import _ "rsc.io/quote" + diff --git a/libgo/go/cmd/go/testdata/script/mod_import_mod.txt b/libgo/go/cmd/go/testdata/script/mod_import_mod.txt new file mode 100644 index 00000000000..b035e3dec22 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_import_mod.txt @@ -0,0 +1,7 @@ +# Test that GOPATH/pkg/mod is excluded +env GO111MODULE=off +! go list mod/foo +stderr 'disallowed import path' + +-- mod/foo/foo.go -- +package foo diff --git a/libgo/go/cmd/go/testdata/script/mod_init_dep.txt b/libgo/go/cmd/go/testdata/script/mod_init_dep.txt new file mode 100644 index 00000000000..29c840b3833 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_init_dep.txt @@ -0,0 +1,34 @@ +env GO111MODULE=on + +# modconv uses git directly to examine what old 'go get' would +[!net] skip +[!exec:git] skip + +# go build should populate go.mod from Gopkg.lock +cp go.mod1 go.mod +go build +stderr 'copying requirements from Gopkg.lock' +go list -m all +! stderr 'copying requirements from Gopkg.lock' +stdout 'rsc.io/sampler v1.0.0' + +# go list should populate go.mod from Gopkg.lock +cp go.mod1 go.mod +go list +stderr 'copying requirements from Gopkg.lock' +go list +! stderr 'copying requirements from Gopkg.lock' +go list -m all +stdout 'rsc.io/sampler v1.0.0' + +-- go.mod1 -- +module x + +-- x.go -- +package x + +-- Gopkg.lock -- +[[projects]] + name = "rsc.io/sampler" + version = "v1.0.0" + diff --git a/libgo/go/cmd/go/testdata/script/mod_install_versioned.txt b/libgo/go/cmd/go/testdata/script/mod_install_versioned.txt new file mode 100644 index 00000000000..03986d06a0a --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_install_versioned.txt @@ -0,0 +1,12 @@ +env GO111MODULE=on + +go list -f '{{.Target}}' rsc.io/fortune +! stdout fortune@v1 +stdout 'fortune(\.exe)?$' + +go list -f '{{.Target}}' rsc.io/fortune/v2 +! stdout v2 +stdout 'fortune(\.exe)?$' + +-- go.mod -- +module m diff --git a/libgo/go/cmd/go/testdata/script/mod_internal.txt b/libgo/go/cmd/go/testdata/script/mod_internal.txt new file mode 100644 index 00000000000..84e77c6d83c --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_internal.txt @@ -0,0 +1,102 @@ +env GO111MODULE=on + +# golang.org/x/internal should be importable from other golang.org/x modules. +rm go.mod +go mod init golang.org/x/anything +go build . + +# ...and their tests... +go test +stdout PASS + +# ...but that should not leak into other modules. +! go build ./baddep +stderr golang.org[/\\]notx[/\\]useinternal +stderr 'use of internal package golang.org/x/.* not allowed' + +# Internal packages in the standard library should not leak into modules. +! go build ./fromstd +[!gccgo] stderr 'use of internal package internal/testenv not allowed' + +# Packages found via standard-library vendoring should not leak. +! go build ./fromstdvendor +[!gccgo] stderr 'use of vendored package golang_org/x/net/http/httpguts not allowed' + +env GO111MODULE=off +! go build ./fromstdvendor +[!gccgo] stderr 'cannot find package "golang_org/x/net/http/httpguts" in any of:' +env GO111MODULE=on + +# Dependencies should be able to use their own internal modules... +rm go.mod +go mod init golang.org/notx +go build ./throughdep + +# ... but other modules should not, even if they have transitive dependencies. +! go build . +stderr 'use of internal package golang.org/x/.* not allowed' + +# And transitive dependencies still should not leak. +! go build ./baddep +stderr golang.org[/\\]notx[/\\]useinternal +stderr 'use of internal package golang.org/x/.* not allowed' + +# Replacing an internal module should keep it internal to the same paths. +rm go.mod +go mod init golang.org/notx +go mod edit -replace golang.org/x/internal=./replace/golang.org/notx/internal +go build ./throughdep + +! go build ./baddep +stderr golang.org[/\\]notx[/\\]useinternal +stderr 'use of internal package golang.org/x/.* not allowed' + +go mod edit -replace golang.org/x/internal=./vendor/golang.org/x/internal +go build ./throughdep + +! go build ./baddep +stderr golang.org[/\\]notx[/\\]useinternal +stderr 'use of internal package golang.org/x/.* not allowed' + +-- useinternal.go -- +package useinternal +import _ "golang.org/x/internal/subtle" + +-- useinternal_test.go -- +package useinternal_test +import ( + "testing" + _ "golang.org/x/internal/subtle" +) + +func Test(*testing.T) {} + +-- throughdep/useinternal.go -- +package throughdep +import _ "golang.org/x/useinternal" + +-- baddep/useinternal.go -- +package baddep +import _ "golang.org/notx/useinternal" + +-- fromstd/useinternal.go -- +package fromstd +import _ "internal/testenv" + +-- fromstdvendor/useinternal.go -- +package fromstdvendor +import _ "golang_org/x/net/http/httpguts" + +-- replace/golang.org/notx/internal/go.mod -- +module golang.org/x/internal + +-- replace/golang.org/notx/internal/subtle/subtle.go -- +package subtle +// Ha ha! Nothing here! + +-- vendor/golang.org/x/internal/go.mod -- +module golang.org/x/internal + +-- vendor/golang.org/x/internal/subtle/subtle.go -- +package subtle +// Ha ha! Nothing here! diff --git a/libgo/go/cmd/go/testdata/script/mod_list.txt b/libgo/go/cmd/go/testdata/script/mod_list.txt new file mode 100644 index 00000000000..2fa079f49ae --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_list.txt @@ -0,0 +1,60 @@ +env GO111MODULE=on + +# list {{.Dir}} shows main module and go.mod but not not-yet-downloaded dependency dir. +go list -m -f '{{.Path}} {{.Main}} {{.GoMod}} {{.Dir}}' all +stdout '^x true .*[\\/]src[\\/]go.mod .*[\\/]src$' +stdout '^rsc.io/quote false .*[\\/]v1.5.2.mod $' + +# list {{.Dir}} shows dependency after download (and go list without -m downloads it) +go list -f '{{.Dir}}' rsc.io/quote +stdout '.*mod[\\/]rsc.io[\\/]quote@v1.5.2$' + +# downloaded dependencies are read-only +exists -readonly $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 +exists -readonly $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/buggy + +# go clean -modcache can delete read-only dependencies +go clean -modcache +! exists $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 + +# list {{.Dir}} shows replaced directories +cp go.mod2 go.mod +go list -f {{.Dir}} rsc.io/quote +go list -m -f '{{.Path}} {{.Version}} {{.Dir}}{{with .Replace}} {{.GoMod}} => {{.Version}} {{.Dir}} {{.GoMod}}{{end}}' all +stdout 'mod[\\/]rsc.io[\\/]quote@v1.5.1' +stdout 'v1.3.0.*mod[\\/]rsc.io[\\/]sampler@v1.3.1 .*[\\/]v1.3.1.mod => v1.3.1.*sampler@v1.3.1 .*[\\/]v1.3.1.mod' + +# list std should work +go list std +[!gccgo] stdout ^math/big + +# rsc.io/quote/buggy should be listable as a package +go list rsc.io/quote/buggy + +# rsc.io/quote/buggy should not be listable as a module +go list -m -e -f '{{.Error.Err}}' nonexist rsc.io/quote/buggy +stdout '^module "nonexist" is not a known dependency' +stdout '^module "rsc.io/quote/buggy" is not a known dependency' + +! go list -m nonexist rsc.io/quote/buggy +stderr '^go list -m nonexist: module "nonexist" is not a known dependency' +stderr '^go list -m rsc.io/quote/buggy: module "rsc.io/quote/buggy" is not a known dependency' + +# Module loader does not interfere with list -e (golang.org/issue/24149). +[!gccgo] go list -e -f '{{.Error.Err}}' database +[!gccgo] stdout 'no Go files in ' +[!gccgo] ! go list database +[!gccgo] stderr 'no Go files in ' + +-- go.mod -- +module x +require rsc.io/quote v1.5.2 + +-- go.mod2 -- +module x +require rsc.io/quote v1.5.1 +replace rsc.io/sampler v1.3.0 => rsc.io/sampler v1.3.1 + +-- x.go -- +package x +import _ "rsc.io/quote" diff --git a/libgo/go/cmd/go/testdata/script/mod_list_bad_import.txt b/libgo/go/cmd/go/testdata/script/mod_list_bad_import.txt new file mode 100644 index 00000000000..258eb6a5671 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_list_bad_import.txt @@ -0,0 +1,73 @@ +# This test matches list_bad_import, but in module mode. +# Please keep them in sync. + +env GO111MODULE=on +cd example.com + +# Without -e, listing an otherwise-valid package with an unsatisfied direct import should fail. +# BUG: Today it succeeds. +go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}} {{range .DepsErrors}}bad dep: {{.Err}}{{end}}' example.com/direct +! stdout ^error +stdout 'incomplete' +stdout 'bad dep: .*example.com/notfound' + +# Listing with -deps should also fail. +# BUG: Today, it does not. +# ! go list -deps example.com/direct +# stderr example.com/notfound +go list -deps example.com/direct +stdout example.com/notfound + + +# Listing an otherwise-valid package that imports some *other* package with an +# unsatisfied import should also fail. +# BUG: Today, it succeeds. +go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}} {{range .DepsErrors}}bad dep: {{.Err}}{{end}}' example.com/indirect +! stdout ^error +stdout incomplete +stdout 'bad dep: .*example.com/notfound' + +# Again, -deps should fail. +# BUG: Again, it does not. +# ! go list -deps example.com/indirect +# stderr example.com/notfound +go list -deps example.com/indirect +stdout example.com/notfound + + +# Listing the missing dependency directly should fail outright... +! go list -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}}' example.com/notfound +stderr 'cannot find module providing package example.com/notfound' +! stdout error +! stdout incomplete + +# ...but listing with -e should succeed. +go list -e -f '{{if .Error}}error{{end}} {{if .Incomplete}}incomplete{{end}}' example.com/notfound +stdout error +stdout incomplete + + +# The pattern "all" should match only packages that acutally exist, +# ignoring those whose existence is merely implied by imports. +go list -e -f '{{.ImportPath}} {{.Error}}' all +stdout example.com/direct +stdout example.com/indirect +# TODO: go list creates a dummy package with the import-not-found +# but really the Error belongs on example.com/direct, and this package +# should not be printed. +# ! stdout example.com/notfound + + +-- example.com/go.mod -- +module example.com + +-- example.com/direct/direct.go -- +package direct +import _ "example.com/notfound" + +-- example.com/indirect/indirect.go -- +package indirect +import _ "example.com/direct" + +-- example.com/notfound/README -- +This directory intentionally left blank. diff --git a/libgo/go/cmd/go/testdata/script/mod_list_dir.txt b/libgo/go/cmd/go/testdata/script/mod_list_dir.txt new file mode 100644 index 00000000000..6d9414794e5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_list_dir.txt @@ -0,0 +1,32 @@ +# go list with path to directory should work + +[gccgo] stop + +env GO111MODULE=off +go list -f '{{.ImportPath}}' $GOROOT/src/math +stdout ^math$ + +env GO111MODULE=on +go list -f '{{.ImportPath}}' $GOROOT/src/math +stdout ^math$ +go list -f '{{.ImportPath}}' . +stdout ^x$ +! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 +stderr '^go: no such directory.*quote@v1.5.2' +go mod download rsc.io/quote@v1.5.2 +go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/quote@v1.5.2 +stdout '^rsc.io/quote$' +go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.0 +stdout '^rsc.io/sampler$' +go get -d rsc.io/sampler@v1.3.1 +go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.1 +stdout '^rsc.io/sampler$' +! go list -f '{{.ImportPath}}' $GOPATH/pkg/mod/rsc.io/sampler@v1.3.0 +stderr 'outside available modules' + +-- go.mod -- +module x +require rsc.io/quote v1.5.2 + +-- x.go -- +package x diff --git a/libgo/go/cmd/go/testdata/script/mod_list_upgrade.txt b/libgo/go/cmd/go/testdata/script/mod_list_upgrade.txt new file mode 100644 index 00000000000..474df0dc269 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_list_upgrade.txt @@ -0,0 +1,8 @@ +env GO111MODULE=on + +go list -m -u all +stdout 'rsc.io/quote v1.2.0 \[v1\.5\.2\]' + +-- go.mod -- +module x +require rsc.io/quote v1.2.0 diff --git a/libgo/go/cmd/go/testdata/script/mod_load_badmod.txt b/libgo/go/cmd/go/testdata/script/mod_load_badmod.txt new file mode 100644 index 00000000000..68c8b3792bd --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_load_badmod.txt @@ -0,0 +1,26 @@ +# Unknown lines should be ignored in dependency go.mod files. +env GO111MODULE=on +go list -m all + +# ... and in replaced dependency go.mod files. +cp go.mod go.mod.usesub +go list -m all + +# ... but not in the main module. +cp go.mod.bad go.mod +! go list -m all +stderr 'unknown directive: hello' + +-- go.mod -- +module m +require rsc.io/badmod v1.0.0 +-- go.mod.bad -- +module m +hello world +-- go.mod.usesub -- +module m +require rsc.io/badmod v1.0.0 +replace rsc.io/badmod v1.0.0 => ./sub +-- sub/go.mod -- +module sub +hello world diff --git a/libgo/go/cmd/go/testdata/script/mod_local_replace.txt b/libgo/go/cmd/go/testdata/script/mod_local_replace.txt new file mode 100644 index 00000000000..19bc8f39045 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_local_replace.txt @@ -0,0 +1,23 @@ +# Test that local replacements work even with dummy module names. +# golang.org/issue/24100. + +env GO111MODULE=on + +cd x/y +go list -f '{{.Dir}}' zz +stdout x[/\\]z$ + +-- x/y/go.mod -- +module x/y +require zz v1.0.0 +replace zz v1.0.0 => ../z + +-- x/y/y.go -- +package y +import _ "zz" + +-- x/z/go.mod -- +module x/z + +-- x/z/z.go -- +package z diff --git a/libgo/go/cmd/go/testdata/script/mod_multirepo.txt b/libgo/go/cmd/go/testdata/script/mod_multirepo.txt new file mode 100644 index 00000000000..7f977e80f6e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_multirepo.txt @@ -0,0 +1,40 @@ +env GO111MODULE=on + +# initial standalone module should use no downloaded modules +go list -deps -f {{.Dir}} +! stdout 'pkg[\\/]mod' + +# v2 import should use a downloaded module +# both without an explicit go.mod entry ... +cp tmp/use_v2.go x.go +go list -deps -f {{.Dir}} +stdout 'pkg[\\/]mod[\\/]rsc.io[\\/]quote[\\/]v2@v2.0.1$' + +# ... and with one ... +cp tmp/use_v2.mod go.mod +go list -deps -f {{.Dir}} +stdout 'pkg[\\/]mod[\\/]rsc.io[\\/]quote[\\/]v2@v2.0.1$' + +# ... and even if there is a v2 module in a subdirectory. +mkdir v2 +cp x.go v2/x.go +cp tmp/v2.mod v2/go.mod +go list -deps -f {{.Dir}} +stdout 'pkg[\\/]mod[\\/]rsc.io[\\/]quote[\\/]v2@v2.0.1$' + +-- go.mod -- +module rsc.io/quote + +-- x.go -- +package quote + +-- tmp/use_v2.go -- +package quote +import _ "rsc.io/quote/v2" + +-- tmp/use_v2.mod -- +module rsc.io/quote +require rsc.io/quote/v2 v2.0.1 + +-- tmp/v2.mod -- +package rsc.io/quote/v2 diff --git a/libgo/go/cmd/go/testdata/script/mod_nomod.txt b/libgo/go/cmd/go/testdata/script/mod_nomod.txt new file mode 100644 index 00000000000..c6fb791c514 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_nomod.txt @@ -0,0 +1,43 @@ +# Test go commands with no module. +env GO111MODULE=on + +# go mod edit fails unless given explicit mod file argument +! go mod edit -json +go mod edit -json x.mod + +# bug succeeds +[exec:echo] env BROWSER=echo +[exec:echo] go bug + +# commands that load the package in the current directory fail +! go build +! go fmt +! go generate +! go get +! go install +! go list +! go run x.go +! go test +! go vet + +# clean succeeds, even with -modcache +go clean -modcache + +# doc succeeds for standard library +[!gccgo] go doc unsafe + +# env succeeds +go env + +# tool succeeds +go tool -n test2json + +# version succeeds +go version + +-- x.mod -- +module m + +-- x.go -- +package main +func main() {} diff --git a/libgo/go/cmd/go/testdata/script/mod_patterns.txt b/libgo/go/cmd/go/testdata/script/mod_patterns.txt new file mode 100644 index 00000000000..9b2ebdf02b9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_patterns.txt @@ -0,0 +1,66 @@ +env GO111MODULE=on + +cd m + +# 'go list all' should list all of the packages used (directly or indirectly) by +# the packages in the main module, but no other packages from the standard +# library or active modules. +# +# 'go list ...' should list packages in all active modules and the standard library. +# But not cmd/* - see golang.org/issue/26924. +# +# 'go list example.com/m/...' should list packages in all modules that begin with 'example.com/m/'. +# +# 'go list ./...' should list only packages in the current module, not other active modules. +# +# Warnings about unmatched patterns should only be printed once. +# +# And the go command should be able to keep track of all this! +go list -f '{{.ImportPath}}: {{.Match}}' all ... example.com/m/... ./... ./xyz... +stdout 'example.com/m/useunicode: \[all \.\.\. example.com/m/... ./...\]' +stdout 'example.com/m/useunsafe: \[all \.\.\. example.com/m/... ./...\]' +[cgo] stdout 'example.com/m/useC: \[all \.\.\. example.com/m/... ./...\]' +[!cgo] ! stdout example.com/m/useC +stdout 'example.com/unused/useerrors: \[\.\.\.\]' # but not "all" +stdout 'example.com/m/nested/useencoding: \[\.\.\. example.com/m/...\]' # but NOT "all" or "./..." +[!gccgo] stdout '^unicode: \[all \.\.\.\]' +[!gccgo] stdout '^unsafe: \[all \.\.\.\]' +[!gccgo] stdout 'index/suffixarray: \[\.\.\.\]' +! stdout cmd/pprof # golang.org/issue/26924 + +stderr -count=1 '^go: warning: "./xyz..." matched no packages$' + +env CGO_ENABLED=0 +go list -f '{{.ImportPath}}: {{.Match}}' all ... example.com/m/... ./... ./xyz... +! stdout example.com/m/useC + +-- m/go.mod -- +module example.com/m + +require example.com/unused v0.0.0 // indirect +replace example.com/unused => ../unused + +require example.com/m/nested v0.0.0 // indirect +replace example.com/m/nested => ../nested + +-- m/useC/useC.go -- +package useC +import _ "C" // "C" is a pseudo-package, not an actual one +-- m/useunicode/useunicode.go -- +package useunicode +import _ "unicode" +-- m/useunsafe/useunsafe.go -- +package useunsafe +import _ "unsafe" + +-- unused/go.mod -- +module example.com/unused +-- unused/useerrors/useerrors.go -- +package useerrors +import _ "errors" + +-- nested/go.mod -- +module example.com/m/nested +-- nested/useencoding/useencoding.go -- +package useencoding +import _ "encoding" diff --git a/libgo/go/cmd/go/testdata/script/mod_query.txt b/libgo/go/cmd/go/testdata/script/mod_query.txt new file mode 100644 index 00000000000..4baaaa89ed9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_query.txt @@ -0,0 +1,24 @@ +env GO111MODULE=on + +go list -m -versions rsc.io/quote +stdout '^rsc.io/quote v1.0.0 v1.1.0 v1.2.0 v1.2.1 v1.3.0 v1.4.0 v1.5.0 v1.5.1 v1.5.2 v1.5.3-pre1$' + +# latest rsc.io/quote should be v1.5.2 not v1.5.3-pre1 +go list -m rsc.io/quote@latest +stdout 'rsc.io/quote v1.5.2$' + +go list -m rsc.io/quote@>v1.5.2 +stdout 'rsc.io/quote v1.5.3-pre1$' + +go list -m rsc.io/quote@v1.5.3 +stderr 'go list -m rsc.io/quote: no matching versions for query ">v1.5.3"' + +go list -m -e -f '{{.Error.Err}}' rsc.io/quote@>v1.5.3 +stdout 'no matching versions for query ">v1.5.3"' + +-- go.mod -- +module x +require rsc.io/quote v1.0.0 diff --git a/libgo/go/cmd/go/testdata/script/mod_query_exclude.txt b/libgo/go/cmd/go/testdata/script/mod_query_exclude.txt new file mode 100644 index 00000000000..a64a8e10866 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_query_exclude.txt @@ -0,0 +1,26 @@ +env GO111MODULE=on + +# get excluded version +cp go.mod1 go.mod +! go get rsc.io/quote@v1.5.0 +stderr 'rsc.io/quote@v1.5.0 excluded' + +# get non-excluded version +cp go.mod1 go.mod +go get rsc.io/quote@v1.5.1 +stderr 'rsc.io/quote v1.5.1' + +# get range with excluded version +cp go.mod1 go.mod +go get rsc.io/quote@>=v1.5 +go list -m ...quote +stdout 'rsc.io/quote v1.5.[1-9]' + +-- go.mod1 -- +module x +exclude rsc.io/quote v1.5.0 + +-- x.go -- +package x +import _ "rsc.io/quote" + diff --git a/libgo/go/cmd/go/testdata/script/mod_readonly.txt b/libgo/go/cmd/go/testdata/script/mod_readonly.txt new file mode 100644 index 00000000000..1b5932e441e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_readonly.txt @@ -0,0 +1,42 @@ +env GO111MODULE=on + +# -mod=readonly must not resolve missing modules nor update go.mod +# +# TODO(bcmills): 'go list' should suffice, but today it does not fail due to +# unresolved imports. When that is fixed, use 'go list' instead of 'go list all'. +env GOFLAGS=-mod=readonly +go mod edit -fmt +cp go.mod go.mod.empty +! go list all +stderr 'import lookup disabled by -mod=readonly' +cmp go.mod go.mod.empty + +# update go.mod - go get allowed +go get rsc.io/quote +grep rsc.io/quote go.mod + +# update go.mod - go mod tidy allowed +cp go.mod.empty go.mod +go mod tidy + +# -mod=readonly must succeed once go.mod is up-to-date... +go list + +# ... even if it needs downloads +go clean -modcache +go list + +# -mod=readonly should reject inconsistent go.mod files +# (ones that would be rewritten). +go mod edit -require rsc.io/sampler@v1.2.0 +cp go.mod go.mod.inconsistent +! go list +stderr 'go: updates to go.mod needed, disabled by -mod=readonly' +cmp go.mod go.mod.inconsistent + +-- go.mod -- +module m + +-- x.go -- +package x +import _ "rsc.io/quote" diff --git a/libgo/go/cmd/go/testdata/script/mod_replace.txt b/libgo/go/cmd/go/testdata/script/mod_replace.txt new file mode 100644 index 00000000000..5894ed69f34 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_replace.txt @@ -0,0 +1,87 @@ +env GO111MODULE=on + +go build -o a1.exe . +exec ./a1.exe +stdout 'Don''t communicate by sharing memory' + +# Modules can be replaced by local packages. +go mod edit -replace=rsc.io/quote/v3=./local/rsc.io/quote/v3 +go build -o a2.exe . +exec ./a2.exe +stdout 'Concurrency is not parallelism.' + +# The module path of the replacement doesn't need to match. +# (For example, it could be a long-running fork with its own import path.) +go mod edit -replace=rsc.io/quote/v3=./local/not-rsc.io/quote/v3 +go build -o a3.exe . +exec ./a3.exe +stdout 'Clear is better than clever.' + +# However, the same module can't be used as two different paths. +go mod edit -dropreplace=rsc.io/quote/v3 -replace=not-rsc.io/quote/v3@v3.0.0=rsc.io/quote/v3@v3.0.0 -require=not-rsc.io/quote/v3@v3.0.0 +! go build -o a4.exe . +stderr 'rsc.io/quote/v3@v3.0.0 used for two different module paths \(not-rsc.io/quote/v3 and rsc.io/quote/v3\)' + +-- go.mod -- +module quoter + +require rsc.io/quote/v3 v3.0.0 + +-- main.go -- +package main + +import ( + "fmt" + "rsc.io/quote/v3" +) + +func main() { + fmt.Println(quote.GoV3()) +} + +-- local/rsc.io/quote/v3/go.mod -- +module rsc.io/quote/v3 + +require rsc.io/sampler v1.3.0 + +-- local/rsc.io/quote/v3/quote.go -- +// 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 quote collects pithy sayings. +package quote + +import "rsc.io/sampler" + +// Hello returns a greeting. +func HelloV3() string { + return sampler.Hello() +} + +// Glass returns a useful phrase for world travelers. +func GlassV3() string { + // See http://www.oocities.org/nodotus/hbglass.html. + return "I can eat glass and it doesn't hurt me." +} + +// Go returns a REPLACED Go proverb. +func GoV3() string { + return "Concurrency is not parallelism." +} + +// Opt returns a optimization truth. +func OptV3() string { + // Wisdom from ken. + return "If a program is too slow, it must have a loop." +} + +-- local/not-rsc.io/quote/v3/go.mod -- +module not-rsc.io/quote/v3 + +-- local/not-rsc.io/quote/v3/quote.go -- +package quote + +func GoV3() string { + return "Clear is better than clever." +} diff --git a/libgo/go/cmd/go/testdata/script/mod_require_exclude.txt b/libgo/go/cmd/go/testdata/script/mod_require_exclude.txt new file mode 100644 index 00000000000..60f7e3fa913 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_require_exclude.txt @@ -0,0 +1,33 @@ +# build with no newer version to satisfy exclude +env GO111MODULE=on +! go list -m all +stderr 'no newer version available' + +# build with newer version available +cp go.mod2 go.mod +go list -m all +stdout 'rsc.io/quote v1.5.2' + +# build with excluded newer version +cp go.mod3 go.mod +go list -m all +stdout 'rsc.io/quote v1.5.1' + +-- x.go -- +package x +import _ "rsc.io/quote" + +-- go.mod -- +module x +exclude rsc.io/sampler latest +require rsc.io/sampler latest + +-- go.mod2 -- +module x +exclude rsc.io/quote v1.5.1 +require rsc.io/quote v1.5.1 + +-- go.mod3 -- +module x +exclude rsc.io/quote v1.5.2 +require rsc.io/quote v1.5.1 diff --git a/libgo/go/cmd/go/testdata/script/mod_test.txt b/libgo/go/cmd/go/testdata/script/mod_test.txt new file mode 100644 index 00000000000..caeb25ada84 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_test.txt @@ -0,0 +1,119 @@ +env GO111MODULE=on + +# A test in the module's root package should work. +cd a/ +cp go.mod.empty go.mod +go test +stdout PASS + +cp go.mod.empty go.mod +go list -deps +! stdout ^testing$ + +# list all should include test dependencies, like testing +cp go.mod.empty go.mod +go list all +stdout ^testing$ +stdout ^rsc.io/quote$ +stdout ^rsc.io/testonly$ + +# list -deps -tests should also include testing +# but not deps of tests of deps (rsc.io/testonly). +go list -deps -test +stdout ^testing$ +stdout ^rsc.io/quote$ +! stdout ^rsc.io/testonly$ + +# list -test all should succeed +cp go.mod.empty go.mod +go list -test all +stdout '^testing' + +cp go.mod.empty go.mod +go test +stdout PASS + +# A test with the "_test" suffix in the module root should also work. +cd ../b/ +go test +stdout PASS + +# A test with the "_test" suffix of a *package* with a "_test" suffix should +# even work (not that you should ever do that). +cd ../c_test +go test +stdout PASS + +cd ../d_test +go test +stdout PASS + +-- a/go.mod.empty -- +module example.com/user/a + +-- a/a.go -- +package a + +-- a/a_test.go -- +package a + +import "testing" +import _ "rsc.io/quote" + +func Test(t *testing.T) {} + +-- b/go.mod -- +module example.com/user/b + +-- b/b.go -- +package b + +-- b/b_test.go -- +package b_test + +import "testing" + +func Test(t *testing.T) {} + +-- c_test/go.mod -- +module example.com/c_test + +-- c_test/umm.go -- +// Package c_test is the non-test package for its import path! +package c_test + +-- c_test/c_test_test.go -- +package c_test_test + +import "testing" + +func Test(t *testing.T) {} + +-- d_test/go.mod -- +// Package d is an ordinary package in a deceptively-named directory. +module example.com/d + +-- d_test/d.go -- +package d + +-- d_test/d_test.go -- +package d_test + +import "testing" + +func Test(t *testing.T) {} + +-- e/go.mod -- +module example.com/e_test + +-- e/wat.go -- +// Package e_test is the non-test package for its import path, +// in a deceptively-named directory! +package e_test + +-- e/e_test.go -- +package e_test_test + +import "testing" + +func Test(t *testing.T) {} diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy.txt b/libgo/go/cmd/go/testdata/script/mod_tidy.txt new file mode 100644 index 00000000000..449aa073a78 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy.txt @@ -0,0 +1,64 @@ +env GO111MODULE=on + +# tidy removes unused y, but everything else is used +go mod tidy -v +stderr '^unused y.1' +! stderr '^unused [^y]' + +go list -m all +! stdout '^y' +stdout '^w.1 v1.2.0' +stdout '^z.1 v1.2.0' + +# empty tidy should not crash +cd triv +go mod tidy + +-- go.mod -- +module m + +require ( + x.1 v1.0.0 + y.1 v1.0.0 + w.1 v1.2.0 +) + +replace x.1 v1.0.0 => ./x +replace y.1 v1.0.0 => ./y +replace z.1 v1.1.0 => ./z +replace z.1 v1.2.0 => ./z +replace w.1 => ./w + +-- m.go -- +package m + +import _ "x.1" +import _ "z.1/sub" + +-- w/go.mod -- +module w + +-- w/w.go -- +package w + +-- x/go.mod -- +module x +require w.1 v1.1.0 +require z.1 v1.1.0 + +-- x/x.go -- +package x +import _ "w.1" + +-- y/go.mod -- +module y +require z.1 v1.2.0 + +-- z/go.mod -- +module z + +-- z/sub/sub.go -- +package sub + +-- triv/go.mod -- +module triv diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_quote.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_quote.txt new file mode 100644 index 00000000000..423c7c246f9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_quote.txt @@ -0,0 +1,26 @@ +# Check that mod tidy does not introduce repeated +# require statements when input go.mod has quoted requirements. +env GO111MODULE=on + +go mod tidy +grep -count=1 rsc.io/quote go.mod + +cp go.mod2 go.mod +go mod tidy +grep -count=1 rsc.io/quote go.mod + + +-- go.mod -- +module x + +-- x.go -- +package x +import "rsc.io/quote" +func main() { _ = quote.Hello } + +-- go.mod2 -- +module x +require ( + "rsc.io/sampler" v1.3.0 + "rsc.io/quote" v1.5.2 +) diff --git a/libgo/go/cmd/go/testdata/script/mod_tidy_sum.txt b/libgo/go/cmd/go/testdata/script/mod_tidy_sum.txt new file mode 100644 index 00000000000..5a15818543e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_tidy_sum.txt @@ -0,0 +1,33 @@ +env GO111MODULE=on + +# go.sum should list directly used modules and dependencies +go get rsc.io/quote@v1.5.2 +go mod tidy +grep rsc.io/sampler go.sum + +# go.sum should not normally lose old entries +go get rsc.io/quote@v1.0.0 +grep 'rsc.io/quote v1.0.0' go.sum +grep 'rsc.io/quote v1.5.2' go.sum +grep rsc.io/sampler go.sum + +# go mod tidy should clear dead entries from go.sum +go mod tidy +grep 'rsc.io/quote v1.0.0' go.sum +! grep 'rsc.io/quote v1.5.2' go.sum +! grep rsc.io/sampler go.sum + +# go.sum with no entries is OK to keep +# (better for version control not to delete and recreate.) +cp x.go.noimports x.go +go mod tidy +exists go.sum +! grep . go.sum + +-- go.mod -- +module x +-- x.go -- +package x +import _ "rsc.io/quote" +-- x.go.noimports -- +package x diff --git a/libgo/go/cmd/go/testdata/script/mod_upgrade_patch.txt b/libgo/go/cmd/go/testdata/script/mod_upgrade_patch.txt new file mode 100644 index 00000000000..3c27cdbf7bb --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_upgrade_patch.txt @@ -0,0 +1,29 @@ +env GO111MODULE=on + +go list -m all +stdout '^rsc.io/quote v1.4.0' +stdout '^rsc.io/sampler v1.0.0' + +# get -u=patch rsc.io/quote should take latest quote & patch update its deps +go get -m -u=patch rsc.io/quote +go list -m all +stdout '^rsc.io/quote v1.5.2' +stdout '^rsc.io/sampler v1.3.1' +stdout '^golang.org/x/text v0.0.0-' + +# get -u=patch quote@v1.2.0 should take that version of quote & patch update its deps +go get -m -u=patch rsc.io/quote@v1.2.0 +go list -m all +stdout '^rsc.io/quote v1.2.0' +stdout '^rsc.io/sampler v1.3.1' +stdout '^golang.org/x/text v0.0.0-' + +# get -u=patch with no args applies to all deps +go get -m -u=patch +go list -m all +stdout '^rsc.io/quote v1.2.1' + +-- go.mod -- +module x +require rsc.io/quote v1.4.0 + diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor.txt b/libgo/go/cmd/go/testdata/script/mod_vendor.txt new file mode 100644 index 00000000000..b3769a85041 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_vendor.txt @@ -0,0 +1,230 @@ +env GO111MODULE=on + +go list -m all +stdout '^x v1.0.0 => ./x' +stdout '^w' + +[!short] go build +[!short] ! go build -mod=vendor + +go list -f {{.Dir}} x +stdout 'src[\\/]x' + +go mod vendor -v +stderr '^# x v1.0.0 => ./x' +stderr '^x' +stderr '^# y v1.0.0 => ./y' +stderr '^y' +stderr '^# z v1.0.0 => ./z' +stderr '^z' +! stderr '^w' + +go list -f {{.Dir}} x +stdout 'src[\\/]x' + +go list -f {{.Dir}} -m x +stdout 'src[\\/]x' + +go list -mod=vendor -f {{.Dir}} x +stdout 'src[\\/]vendor[\\/]x' + +go list -mod=vendor -f {{.Dir}} -m x +stdout 'src[\\/]vendor[\\/]x' + +go list -f {{.Dir}} -m w +stdout 'src[\\/]w' + +! go list -mod=vendor -f {{.Dir}} w +stderr 'src[\\/]vendor[\\/]w' + +! exists vendor/x/testdata +! exists vendor/a/foo/bar/b/main_test.go + +exists vendor/a/foo/AUTHORS.txt +exists vendor/a/foo/CONTRIBUTORS +exists vendor/a/foo/LICENSE +exists vendor/a/foo/PATENTS +exists vendor/a/foo/COPYING +exists vendor/a/foo/COPYLEFT +exists vendor/x/NOTICE! +exists vendor/mysite/myname/mypkg/LICENSE.txt + +! exists vendor/a/foo/licensed-to-kill +! exists vendor/w +! exists vendor/w/LICENSE +! exists vendor/x/x2 +! exists vendor/x/x2/LICENSE + +[short] stop + +go build +go build -mod=vendor +go test -mod=vendor . ./subdir +go test -mod=vendor ./... + +-- go.mod -- +module m + +require ( + a v1.0.0 + mysite/myname/mypkg v1.0.0 + w v1.0.0 // indirect + x v1.0.0 + y v1.0.0 + z v1.0.0 +) + +replace ( + a v1.0.0 => ./a + mysite/myname/mypkg v1.0.0 => ./mypkg + w v1.0.0 => ./w + x v1.0.0 => ./x + y v1.0.0 => ./y + z v1.0.0 => ./z +) + +-- a/foo/AUTHORS.txt -- +-- a/foo/CONTRIBUTORS -- +-- a/foo/LICENSE -- +-- a/foo/PATENTS -- +-- a/foo/COPYING -- +-- a/foo/COPYLEFT -- +-- a/foo/licensed-to-kill -- +-- w/LICENSE -- +-- x/NOTICE! -- +-- x/x2/LICENSE -- +-- mypkg/LICENSE.txt -- + +-- a/foo/bar/b/main.go -- +package b +-- a/foo/bar/b/main_test.go -- +package b + +import ( + "os" + "testing" +) + +func TestDir(t *testing.T) { + if _, err := os.Stat("../testdata/1"); err != nil { + t.Fatalf("testdata: %v", err) + } +} +-- a/foo/bar/c/main.go -- +package c +-- a/foo/bar/c/main_test.go -- +package c + +import ( + "os" + "testing" +) + +func TestDir(t *testing.T) { + if _, err := os.Stat("../../../testdata/1"); err != nil { + t.Fatalf("testdata: %v", err) + } + if _, err := os.Stat("./testdata/1"); err != nil { + t.Fatalf("testdata: %v", err) + } +} +-- a/foo/bar/c/testdata/1 -- +-- a/foo/bar/testdata/1 -- +-- a/go.mod -- +module a +-- a/main.go -- +package a +-- a/main_test.go -- +package a + +import ( + "os" + "testing" +) + +func TestDir(t *testing.T) { + if _, err := os.Stat("./testdata/1"); err != nil { + t.Fatalf("testdata: %v", err) + } +} +-- a/testdata/1 -- +-- appengine.go -- +// +build appengine + +package m + +import _ "appengine" +import _ "appengine/datastore" +-- nonexistent.go -- +// +build alternatereality + +package m + +import _ "nonexistent.rsc.io" +-- mypkg/go.mod -- +module me +-- mypkg/mydir/d.go -- +package mydir +-- subdir/v1_test.go -- +package m + +import _ "mysite/myname/mypkg/mydir" +-- testdata1.go -- +package m + +import _ "a" +-- testdata2.go -- +package m + +import _ "a/foo/bar/b" +import _ "a/foo/bar/c" +-- v1.go -- +package m + +import _ "x" +-- v2.go -- +// +build abc + +package mMmMmMm + +import _ "y" +-- v3.go -- +// +build !abc + +package m + +import _ "z" +-- v4.go -- +// +build notmytag + +package m + +import _ "x/x1" +-- w/go.mod -- +module w +-- w/w.go -- +package w +-- x/go.mod -- +module x +-- x/testdata/x.txt -- +placeholder - want directory with no go files +-- x/x.go -- +package x +-- x/x1/x1.go -- +// +build notmytag + +package x1 +-- x/x2/dummy.txt -- +dummy +-- x/x_test.go -- +package x + +import _ "w" +-- y/go.mod -- +module y +-- y/y.go -- +package y +-- z/go.mod -- +module z +-- z/z.go -- +package z diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_build.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_build.txt new file mode 100644 index 00000000000..7b304dbb707 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_vendor_build.txt @@ -0,0 +1,27 @@ +env GO111MODULE=on + +# initial conditions: using sampler v1.3.0, not listed in go.mod. +go list -deps +stdout rsc.io/sampler +! grep 'rsc.io/sampler v1.3.0' go.mod + +# update to v1.3.1, now indirect in go.mod. +go get rsc.io/sampler@v1.3.1 +grep 'rsc.io/sampler v1.3.1 // indirect' go.mod +cp go.mod go.mod.good + +# vendoring can but should not need to make changes. +go mod vendor +cmp go.mod go.mod.good + +# go list -mod=vendor (or go build -mod=vendor) must not modify go.mod. +# golang.org/issue/26704 +go list -mod=vendor +cmp go.mod go.mod.good + +-- go.mod -- +module m + +-- x.go -- +package x +import _ "rsc.io/quote" diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor_nodeps.txt b/libgo/go/cmd/go/testdata/script/mod_vendor_nodeps.txt new file mode 100644 index 00000000000..e9a84ca9860 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_vendor_nodeps.txt @@ -0,0 +1,9 @@ +env GO111MODULE=on + +go mod vendor +stderr '^go: no dependencies to vendor' + +-- go.mod -- +module x +-- x.go -- +package x diff --git a/libgo/go/cmd/go/testdata/script/mod_verify.txt b/libgo/go/cmd/go/testdata/script/mod_verify.txt new file mode 100644 index 00000000000..50c9b4a4375 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_verify.txt @@ -0,0 +1,85 @@ +env GO111MODULE=on + +# With good go.sum, verify succeeds by avoiding download. +cp go.sum.good go.sum +go mod verify +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.zip + +# With bad go.sum, verify succeeds by avoiding download. +cp go.sum.bad go.sum +go mod verify +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.zip + +# With bad go.sum, sync (which must download) fails. +# Even if the bad sum is in the old legacy go.modverify file. +rm go.sum +cp go.sum.bad go.modverify +! go mod tidy +stderr 'checksum mismatch' +! exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.zip + +# With good go.sum, sync works (and moves go.modverify to go.sum). +rm go.sum +cp go.sum.good go.modverify +go mod tidy +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.zip +exists $GOPATH/pkg/mod/rsc.io/quote@v1.1.0/quote.go +! exists go.modverify + +# go.sum should have the new checksum for go.mod +grep '^rsc.io/quote v1.1.0/go.mod ' go.sum + +# verify should work +go mod verify + +# basic loading of module graph should detect incorrect go.mod files. +go mod graph +cp go.sum.bad2 go.sum +! go mod graph +stderr 'go.mod: checksum mismatch' + +# go.sum should be created and updated automatically. +rm go.sum +go mod graph +exists go.sum +grep '^rsc.io/quote v1.1.0/go.mod ' go.sum +! grep '^rsc.io/quote v1.1.0 ' go.sum + +go mod tidy +grep '^rsc.io/quote v1.1.0/go.mod ' go.sum +grep '^rsc.io/quote v1.1.0 ' go.sum + +# sync should ignore missing ziphash; verify should not +rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.ziphash +go mod tidy +! go mod verify + +# Packages below module root should not be mentioned in go.sum. +rm go.sum +go mod edit -droprequire rsc.io/quote +go list rsc.io/quote/buggy # re-resolves import path and updates go.mod +grep '^rsc.io/quote v1.5.2/go.mod ' go.sum +! grep buggy go.sum + +# non-existent packages below module root should not be mentioned in go.sum +go mod edit -droprequire rsc.io/quote +! go list rsc.io/quote/morebuggy +grep '^rsc.io/quote v1.5.2/go.mod ' go.sum +! grep buggy go.sum + +-- go.mod -- +module x +require rsc.io/quote v1.1.0 + +-- x.go -- +package x +import _ "rsc.io/quote" + +-- go.sum.good -- +rsc.io/quote v1.1.0 h1:a3YaZoizPtXyv6ZsJ74oo2L4/bwOSTKMY7MAyo4O/0c= + +-- go.sum.bad -- +rsc.io/quote v1.1.0 h1:a3YaZoizPtXyv6ZsJ74oo2L4/bwOSTKMY7MAyo4O/1c= + +-- go.sum.bad2 -- +rsc.io/quote v1.1.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl1= diff --git a/libgo/go/cmd/go/testdata/script/mod_versions.txt b/libgo/go/cmd/go/testdata/script/mod_versions.txt new file mode 100644 index 00000000000..fd5e5c589d2 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_versions.txt @@ -0,0 +1,14 @@ +# Test rejection of pkg@version in GOPATH mode. +env GO111MODULE=off +! go get rsc.io/quote@v1.5.1 +stderr 'cannot use path@version syntax in GOPATH mode' +! go build rsc.io/quote@v1.5.1 +stderr 'cannot use path@version syntax in GOPATH mode' + +env GO111MODULE=on +cd x +! go build rsc.io/quote@v1.5.1 +stderr 'can only use path@version syntax with ''go get''' + +-- x/go.mod -- +module x diff --git a/libgo/go/cmd/go/testdata/script/mod_why.txt b/libgo/go/cmd/go/testdata/script/mod_why.txt new file mode 100644 index 00000000000..4d556fc73ff --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/mod_why.txt @@ -0,0 +1,114 @@ +env GO111MODULE=on + +go list -test all +stdout rsc.io/quote +stdout golang.org/x/text/language + +# why a package? +go mod why golang.org/x/text/language +cmp stdout why-language.txt + +# why a module? +go mod why -m golang.org... +cmp stdout why-text-module.txt + +# why a package used only in tests? +go mod why rsc.io/testonly +cmp stdout why-testonly.txt + +# why a module used only in tests? +go mod why -m rsc.io/testonly +cmp stdout why-testonly.txt + +# test package not needed +go mod why golang.org/x/text/unused +cmp stdout why-unused.txt + +# vendor doesn't use packages used only in tests. +go mod why -vendor rsc.io/testonly +cmp stdout why-vendor.txt + +# vendor doesn't use modules used only in tests. +go mod why -vendor -m rsc.io/testonly +cmp stdout why-vendor-module.txt + +# test multiple packages +go mod why golang.org/x/text/language golang.org/x/text/unused +cmp stdout why-both.txt + +# test multiple modules +go mod why -m rsc.io/quote rsc.io/sampler +cmp stdout why-both-module.txt + +-- go.mod -- +module mymodule +require rsc.io/quote v1.5.2 + +-- x/x.go -- +package x +import _ "mymodule/z" + +-- y/y.go -- +package y + +-- y/y_test.go -- +package y +import _ "rsc.io/quote" + +-- z/z.go -- +package z +import _ "mymodule/y" + + +-- why-language.txt -- +# golang.org/x/text/language +mymodule/y +mymodule/y.test +rsc.io/quote +rsc.io/sampler +golang.org/x/text/language +-- why-unused.txt -- +# golang.org/x/text/unused +(main module does not need package golang.org/x/text/unused) +-- why-text-module.txt -- +# golang.org/x/text +mymodule/y +mymodule/y.test +rsc.io/quote +rsc.io/sampler +golang.org/x/text/language +-- why-testonly.txt -- +# rsc.io/testonly +mymodule/y +mymodule/y.test +rsc.io/quote +rsc.io/sampler +rsc.io/sampler.test +rsc.io/testonly +-- why-vendor.txt -- +# rsc.io/testonly +(main module does not need to vendor package rsc.io/testonly) +-- why-vendor-module.txt -- +# rsc.io/testonly +(main module does not need to vendor module rsc.io/testonly) +-- why-both.txt -- +# golang.org/x/text/language +mymodule/y +mymodule/y.test +rsc.io/quote +rsc.io/sampler +golang.org/x/text/language + +# golang.org/x/text/unused +(main module does not need package golang.org/x/text/unused) +-- why-both-module.txt -- +# rsc.io/quote +mymodule/y +mymodule/y.test +rsc.io/quote + +# rsc.io/sampler +mymodule/y +mymodule/y.test +rsc.io/quote +rsc.io/sampler diff --git a/libgo/go/cmd/go/testdata/script/pattern_syntax_error.txt b/libgo/go/cmd/go/testdata/script/pattern_syntax_error.txt new file mode 100644 index 00000000000..8e6549b5c54 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/pattern_syntax_error.txt @@ -0,0 +1,10 @@ +# patterns match directories with syntax errors +! go list ./... +! go build ./... +! go install ./... + +-- mypkg/x.go -- +package mypkg + +-- mypkg/y.go -- +pkg mypackage diff --git a/libgo/go/cmd/go/testdata/script/run_hello.txt b/libgo/go/cmd/go/testdata/script/run_hello.txt new file mode 100644 index 00000000000..8c4c1c16833 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/run_hello.txt @@ -0,0 +1,7 @@ +# hello world +go run hello.go +stderr 'hello world' + +-- hello.go -- +package main +func main() { println("hello world") } diff --git a/libgo/go/cmd/go/testdata/script/test_badtest.txt b/libgo/go/cmd/go/testdata/script/test_badtest.txt new file mode 100644 index 00000000000..42fcfed2fcc --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_badtest.txt @@ -0,0 +1,30 @@ +! go test badtest/... +! stdout ^ok +stdout ^FAIL\tbadtest/badexec +stdout ^FAIL\tbadtest/badsyntax +stdout ^FAIL\tbadtest/badvar + +-- badtest/badexec/x_test.go -- +package badexec + +func init() { + panic("badexec") +} + +-- badtest/badsyntax/x.go -- +package badsyntax + +-- badtest/badsyntax/x_test.go -- +package badsyntax + +func func func func func! + +-- badtest/badvar/x.go -- +package badvar + +-- badtest/badvar/x_test.go -- +package badvar_test + +func f() { + _ = notdefined +} diff --git a/libgo/go/cmd/go/testdata/script/test_compile_binary.txt b/libgo/go/cmd/go/testdata/script/test_compile_binary.txt new file mode 100644 index 00000000000..6c01bc5729e --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/test_compile_binary.txt @@ -0,0 +1,6 @@ +! go test -c compile_binary/... +stderr 'build comment' + +-- compile_binary/foo_test.go -- +//+build foo +package foo diff --git a/libgo/go/cmd/go/testdata/script/vendor_complex.txt b/libgo/go/cmd/go/testdata/script/vendor_complex.txt new file mode 100644 index 00000000000..6513451df85 --- /dev/null +++ b/libgo/go/cmd/go/testdata/script/vendor_complex.txt @@ -0,0 +1,73 @@ +# smoke test for complex build configuration +go build -o complex.exe complex +[exec:gccgo] go build -compiler=gccgo -o complex.exe complex + +-- complex/main.go -- +package main + +import ( + _ "complex/nest/sub/test12" + _ "complex/nest/sub/test23" + "complex/w" + "v" +) + +func main() { + println(v.Hello + " " + w.World) +} + +-- complex/nest/sub/test12/p.go -- +package test12 + +// Check that vendor/v1 is used but vendor/v2 is NOT used (sub/vendor/v2 wins). + +import ( + "v1" + "v2" +) + +const x = v1.ComplexNestVendorV1 +const y = v2.ComplexNestSubVendorV2 + +-- complex/nest/sub/test23/p.go -- +package test23 + +// Check that vendor/v3 is used but vendor/v2 is NOT used (sub/vendor/v2 wins). + +import ( + "v2" + "v3" +) + +const x = v3.ComplexNestVendorV3 +const y = v2.ComplexNestSubVendorV2 + +-- complex/nest/sub/vendor/v2/v2.go -- +package v2 + +const ComplexNestSubVendorV2 = true + +-- complex/nest/vendor/v1/v1.go -- +package v1 + +const ComplexNestVendorV1 = true + +-- complex/nest/vendor/v2/v2.go -- +package v2 + +const ComplexNestVendorV2 = true + +-- complex/nest/vendor/v3/v3.go -- +package v3 + +const ComplexNestVendorV3 = true + +-- complex/vendor/v/v.go -- +package v + +const Hello = "hello" + +-- complex/w/w.go -- +package w + +const World = "world" diff --git a/libgo/go/cmd/go/testdata/src/badtest/badexec/x_test.go b/libgo/go/cmd/go/testdata/src/badtest/badexec/x_test.go deleted file mode 100644 index 12f50517125..00000000000 --- a/libgo/go/cmd/go/testdata/src/badtest/badexec/x_test.go +++ /dev/null @@ -1,5 +0,0 @@ -package badexec - -func init() { - panic("badexec") -} diff --git a/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x.go b/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x.go deleted file mode 100644 index c8a5407a5ac..00000000000 --- a/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x.go +++ /dev/null @@ -1 +0,0 @@ -package badsyntax diff --git a/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x_test.go b/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x_test.go deleted file mode 100644 index 5be10745d9b..00000000000 --- a/libgo/go/cmd/go/testdata/src/badtest/badsyntax/x_test.go +++ /dev/null @@ -1,3 +0,0 @@ -package badsyntax - -func func func func func! diff --git a/libgo/go/cmd/go/testdata/src/badtest/badvar/x.go b/libgo/go/cmd/go/testdata/src/badtest/badvar/x.go deleted file mode 100644 index fdd46c4c721..00000000000 --- a/libgo/go/cmd/go/testdata/src/badtest/badvar/x.go +++ /dev/null @@ -1 +0,0 @@ -package badvar diff --git a/libgo/go/cmd/go/testdata/src/badtest/badvar/x_test.go b/libgo/go/cmd/go/testdata/src/badtest/badvar/x_test.go deleted file mode 100644 index c67df01c5ca..00000000000 --- a/libgo/go/cmd/go/testdata/src/badtest/badvar/x_test.go +++ /dev/null @@ -1,5 +0,0 @@ -package badvar_test - -func f() { - _ = notdefined -} diff --git a/libgo/go/cmd/go/testdata/src/complex/main.go b/libgo/go/cmd/go/testdata/src/complex/main.go deleted file mode 100644 index c38df019480..00000000000 --- a/libgo/go/cmd/go/testdata/src/complex/main.go +++ /dev/null @@ -1,12 +0,0 @@ -package main - -import ( - _ "complex/nest/sub/test12" - _ "complex/nest/sub/test23" - "complex/w" - "v" -) - -func main() { - println(v.Hello + " " + w.World) -} diff --git a/libgo/go/cmd/go/testdata/src/complex/nest/sub/test12/p.go b/libgo/go/cmd/go/testdata/src/complex/nest/sub/test12/p.go deleted file mode 100644 index 94943ec1bbe..00000000000 --- a/libgo/go/cmd/go/testdata/src/complex/nest/sub/test12/p.go +++ /dev/null @@ -1,11 +0,0 @@ -package test12 - -// Check that vendor/v1 is used but vendor/v2 is NOT used (sub/vendor/v2 wins). - -import ( - "v1" - "v2" -) - -const x = v1.ComplexNestVendorV1 -const y = v2.ComplexNestSubVendorV2 diff --git a/libgo/go/cmd/go/testdata/src/complex/nest/sub/test23/p.go b/libgo/go/cmd/go/testdata/src/complex/nest/sub/test23/p.go deleted file mode 100644 index 8801a4812af..00000000000 --- a/libgo/go/cmd/go/testdata/src/complex/nest/sub/test23/p.go +++ /dev/null @@ -1,11 +0,0 @@ -package test23 - -// Check that vendor/v3 is used but vendor/v2 is NOT used (sub/vendor/v2 wins). - -import ( - "v2" - "v3" -) - -const x = v3.ComplexNestVendorV3 -const y = v2.ComplexNestSubVendorV2 diff --git a/libgo/go/cmd/go/testdata/src/complex/nest/sub/vendor/v2/v2.go b/libgo/go/cmd/go/testdata/src/complex/nest/sub/vendor/v2/v2.go deleted file mode 100644 index 2991871710e..00000000000 --- a/libgo/go/cmd/go/testdata/src/complex/nest/sub/vendor/v2/v2.go +++ /dev/null @@ -1,3 +0,0 @@ -package v2 - -const ComplexNestSubVendorV2 = true diff --git a/libgo/go/cmd/go/testdata/src/complex/nest/vendor/v1/v1.go b/libgo/go/cmd/go/testdata/src/complex/nest/vendor/v1/v1.go deleted file mode 100644 index a55f5290a9a..00000000000 --- a/libgo/go/cmd/go/testdata/src/complex/nest/vendor/v1/v1.go +++ /dev/null @@ -1,3 +0,0 @@ -package v1 - -const ComplexNestVendorV1 = true diff --git a/libgo/go/cmd/go/testdata/src/complex/nest/vendor/v2/v2.go b/libgo/go/cmd/go/testdata/src/complex/nest/vendor/v2/v2.go deleted file mode 100644 index ac94def4e3e..00000000000 --- a/libgo/go/cmd/go/testdata/src/complex/nest/vendor/v2/v2.go +++ /dev/null @@ -1,3 +0,0 @@ -package v2 - -const ComplexNestVendorV2 = true diff --git a/libgo/go/cmd/go/testdata/src/complex/nest/vendor/v3/v3.go b/libgo/go/cmd/go/testdata/src/complex/nest/vendor/v3/v3.go deleted file mode 100644 index abf99b95745..00000000000 --- a/libgo/go/cmd/go/testdata/src/complex/nest/vendor/v3/v3.go +++ /dev/null @@ -1,3 +0,0 @@ -package v3 - -const ComplexNestVendorV3 = true diff --git a/libgo/go/cmd/go/testdata/src/complex/vendor/v/v.go b/libgo/go/cmd/go/testdata/src/complex/vendor/v/v.go deleted file mode 100644 index bb20d86f25a..00000000000 --- a/libgo/go/cmd/go/testdata/src/complex/vendor/v/v.go +++ /dev/null @@ -1,3 +0,0 @@ -package v - -const Hello = "hello" diff --git a/libgo/go/cmd/go/testdata/src/complex/w/w.go b/libgo/go/cmd/go/testdata/src/complex/w/w.go deleted file mode 100644 index a9c7fbb3094..00000000000 --- a/libgo/go/cmd/go/testdata/src/complex/w/w.go +++ /dev/null @@ -1,3 +0,0 @@ -package w - -const World = "world" diff --git a/libgo/go/cmd/go/testdata/src/failfast_test.go b/libgo/go/cmd/go/testdata/src/failfast_test.go index fef4d2a35e1..6e64d73fdf9 100644 --- a/libgo/go/cmd/go/testdata/src/failfast_test.go +++ b/libgo/go/cmd/go/testdata/src/failfast_test.go @@ -52,3 +52,11 @@ func TestFailingSubtestsA(t *testing.T) { 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/src/hello/hello.go b/libgo/go/cmd/go/testdata/src/hello/hello.go new file mode 100644 index 00000000000..73d83e646f9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/hello/hello.go @@ -0,0 +1,5 @@ +package main + +func main() { + println("hello, world") +} diff --git a/libgo/go/cmd/go/testdata/src/testnorun/p.go b/libgo/go/cmd/go/testdata/src/testnorun/p.go new file mode 100644 index 00000000000..71a9a561ef9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/src/testnorun/p.go @@ -0,0 +1,5 @@ +package p + +func init() { + panic("go test must not link and run test binaries without tests") +} diff --git a/libgo/go/cmd/go/testdata/src/vetfail/p1/p1.go b/libgo/go/cmd/go/testdata/src/vetfail/p1/p1.go index 248317b779a..eaa9b183331 100644 --- a/libgo/go/cmd/go/testdata/src/vetfail/p1/p1.go +++ b/libgo/go/cmd/go/testdata/src/vetfail/p1/p1.go @@ -1,3 +1,5 @@ +// +build !foo-bar + package p1 import "fmt" diff --git a/libgo/go/cmd/go/testdata/testcover/pkg1/a.go b/libgo/go/cmd/go/testdata/testcover/pkg1/a.go new file mode 100644 index 00000000000..e2916119d4f --- /dev/null +++ b/libgo/go/cmd/go/testdata/testcover/pkg1/a.go @@ -0,0 +1,7 @@ +package pkg1 + +import "fmt" + +func F() { + fmt.Println("pkg1") +} diff --git a/libgo/go/cmd/go/testdata/testcover/pkg2/a.go b/libgo/go/cmd/go/testdata/testcover/pkg2/a.go new file mode 100644 index 00000000000..7bd9bd44ee9 --- /dev/null +++ b/libgo/go/cmd/go/testdata/testcover/pkg2/a.go @@ -0,0 +1,7 @@ +package pkg2 + +import "fmt" + +func F() { + fmt.Println("pkg2") +} diff --git a/libgo/go/cmd/go/testdata/testcover/pkg2/a_test.go b/libgo/go/cmd/go/testdata/testcover/pkg2/a_test.go new file mode 100644 index 00000000000..4f791ad6ab0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/testcover/pkg2/a_test.go @@ -0,0 +1 @@ +package pkg2 diff --git a/libgo/go/cmd/go/testdata/testcover/pkg3/a.go b/libgo/go/cmd/go/testdata/testcover/pkg3/a.go new file mode 100644 index 00000000000..bf86ed8dc0e --- /dev/null +++ b/libgo/go/cmd/go/testdata/testcover/pkg3/a.go @@ -0,0 +1,7 @@ +package pkg3 + +import "fmt" + +func F() { + fmt.Println("pkg3") +} diff --git a/libgo/go/cmd/go/testdata/testcover/pkg3/a_test.go b/libgo/go/cmd/go/testdata/testcover/pkg3/a_test.go new file mode 100644 index 00000000000..39c2c5a6fc5 --- /dev/null +++ b/libgo/go/cmd/go/testdata/testcover/pkg3/a_test.go @@ -0,0 +1,7 @@ +package pkg3 + +import "testing" + +func TestF(t *testing.T) { + F() +} diff --git a/libgo/go/cmd/go/testdata/testonly2/t.go b/libgo/go/cmd/go/testdata/testonly2/t.go new file mode 100644 index 00000000000..82267d32e41 --- /dev/null +++ b/libgo/go/cmd/go/testdata/testonly2/t.go @@ -0,0 +1,6 @@ +// This package is not a test-only package, +// but it still matches the pattern ./testdata/testonly... when in cmd/go. + +package main + +func main() {} diff --git a/libgo/go/cmd/go/testdata/vendormod.txt b/libgo/go/cmd/go/testdata/vendormod.txt new file mode 100644 index 00000000000..cd009db5cf0 --- /dev/null +++ b/libgo/go/cmd/go/testdata/vendormod.txt @@ -0,0 +1,160 @@ +generated by: go run savedir.go vendormod + +-- a/foo/AUTHORS.txt -- +-- a/foo/CONTRIBUTORS -- +-- a/foo/LICENSE -- +-- a/foo/PATENTS -- +-- a/foo/COPYING -- +-- a/foo/COPYLEFT -- +-- a/foo/licensed-to-kill -- +-- w/LICENSE -- +-- x/NOTICE! -- +-- x/x2/LICENSE -- +-- mypkg/LICENSE.txt -- +-- a/foo/bar/b/main.go -- +package b +-- a/foo/bar/b/main_test.go -- +package b + +import ( + "os" + "testing" +) + +func TestDir(t *testing.T) { + if _, err := os.Stat("../testdata/1"); err != nil { + t.Fatalf("testdata: %v", err) + } +} +-- a/foo/bar/c/main.go -- +package c +-- a/foo/bar/c/main_test.go -- +package c + +import ( + "os" + "testing" +) + +func TestDir(t *testing.T) { + if _, err := os.Stat("../../../testdata/1"); err != nil { + t.Fatalf("testdata: %v", err) + } + if _, err := os.Stat("./testdata/1"); err != nil { + t.Fatalf("testdata: %v", err) + } +} +-- a/foo/bar/c/testdata/1 -- +-- a/foo/bar/testdata/1 -- +-- a/gcc/go/gofrontend.mod -- +module a +-- a/main.go -- +package a +-- a/main_test.go -- +package a + +import ( + "os" + "testing" +) + +func TestDir(t *testing.T) { + if _, err := os.Stat("./testdata/1"); err != nil { + t.Fatalf("testdata: %v", err) + } +} +-- a/testdata/1 -- +-- appengine.go -- +// +build appengine + +package m + +import _ "appengine" +import _ "appengine/datastore" +-- go.mod -- +module m + +require ( + a v1.0.0 + mysite/myname/mypkg v1.0.0 + w v1.0.0 // indirect + x v1.0.0 + y v1.0.0 + z v1.0.0 +) + +replace ( + a v1.0.0 => ./a + mysite/myname/mypkg v1.0.0 => ./mypkg + w v1.0.0 => ./w + x v1.0.0 => ./x + y v1.0.0 => ./y + z v1.0.0 => ./z +) +-- mypkg/go.mod -- +module me +-- mypkg/mydir/d.go -- +package mydir +-- subdir/v1_test.go -- +package m + +import _ "mysite/myname/mypkg/mydir" +-- testdata1.go -- +package m + +import _ "a" +-- testdata2.go -- +package m + +import _ "a/foo/bar/b" +import _ "a/foo/bar/c" +-- v1.go -- +package m + +import _ "x" +-- v2.go -- +// +build abc + +package mMmMmMm + +import _ "y" +-- v3.go -- +// +build !abc + +package m + +import _ "z" +-- v4.go -- +// +build notmytag + +package m + +import _ "x/x1" +-- w/go.mod -- +module w +-- w/w.go -- +package w +-- x/go.mod -- +module x +-- x/testdata/x.txt -- +placeholder - want directory with no go files +-- x/x.go -- +package x +-- x/x1/x1.go -- +// +build notmytag + +package x1 +-- x/x2/dummy.txt -- +dummy +-- x/x_test.go -- +package x + +import _ "w" +-- y/go.mod -- +module y +-- y/y.go -- +package y +-- z/go.mod -- +module z +-- z/z.go -- +package z diff --git a/libgo/go/cmd/go/vendor_test.go b/libgo/go/cmd/go/vendor_test.go index 0e7a633240b..22aa643b003 100644 --- a/libgo/go/cmd/go/vendor_test.go +++ b/libgo/go/cmd/go/vendor_test.go @@ -332,7 +332,7 @@ func TestVendor12156(t *testing.T) { // Module legacy support does path rewriting very similar to vendoring. -func TestModLegacy(t *testing.T) { +func TestLegacyMod(t *testing.T) { tg := testgo(t) defer tg.cleanup() tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/modlegacy")) @@ -347,7 +347,7 @@ func TestModLegacy(t *testing.T) { tg.run("build", "old/p1", "new/p1") } -func TestModLegacyGet(t *testing.T) { +func TestLegacyModGet(t *testing.T) { testenv.MustHaveExternalNetwork(t) tg := testgo(t) diff --git a/libgo/go/cmd/internal/buildid/note.go b/libgo/go/cmd/internal/buildid/note.go index f0439fb0bfb..2d26ea9961c 100644 --- a/libgo/go/cmd/internal/buildid/note.go +++ b/libgo/go/cmd/internal/buildid/note.go @@ -30,6 +30,7 @@ func ReadELFNote(filename, name string, typ int32) ([]byte, error) { if err != nil { return nil, err } + defer f.Close() for _, sect := range f.Sections { if sect.Type != elf.SHT_NOTE { continue @@ -147,7 +148,7 @@ func readELF(name string, f *os.File, data []byte) (buildid string, err error) { break } off += notesz - align := uint64(p.Align) + align := p.Align alignedOff := (off + align - 1) &^ (align - 1) notesz += alignedOff - off off = alignedOff diff --git a/libgo/go/cmd/internal/objabi/flag.go b/libgo/go/cmd/internal/objabi/flag.go index 1bd4bc9063a..30cd7dccac2 100644 --- a/libgo/go/cmd/internal/objabi/flag.go +++ b/libgo/go/cmd/internal/objabi/flag.go @@ -7,6 +7,9 @@ package objabi import ( "flag" "fmt" + "io" + "io/ioutil" + "log" "os" "strconv" "strings" @@ -20,18 +23,53 @@ func Flagfn1(name, usage string, f func(string)) { flag.Var(fn1(f), name, usage) } -func Flagprint(fd int) { - if fd == 1 { - flag.CommandLine.SetOutput(os.Stdout) - } +func Flagprint(w io.Writer) { + flag.CommandLine.SetOutput(w) flag.PrintDefaults() } func Flagparse(usage func()) { flag.Usage = usage + os.Args = expandArgs(os.Args) flag.Parse() } +// expandArgs expands "response files" arguments in the provided slice. +// +// A "response file" argument starts with '@' and the rest of that +// argument is a filename with CR-or-CRLF-separated arguments. Each +// argument in the named files can also contain response file +// arguments. See Issue 18468. +// +// The returned slice 'out' aliases 'in' iff the input did not contain +// any response file arguments. +// +// TODO: handle relative paths of recursive expansions in different directories? +// Is there a spec for this? Are relative paths allowed? +func expandArgs(in []string) (out []string) { + // out is nil until we see a "@" argument. + for i, s := range in { + if strings.HasPrefix(s, "@") { + if out == nil { + out = make([]string, 0, len(in)*2) + out = append(out, in[:i]...) + } + slurp, err := ioutil.ReadFile(s[1:]) + if err != nil { + log.Fatal(err) + } + args := strings.Split(strings.TrimSpace(strings.Replace(string(slurp), "\r", "", -1)), "\n") + out = append(out, expandArgs(args)...) + } else if out != nil { + out = append(out, s) + } + } + if out == nil { + return in + } + return +} + func AddVersionFlag() { flag.Var(versionFlag{}, "V", "print version and exit") } @@ -107,21 +145,6 @@ func (c *count) IsCountFlag() bool { return true } -type fn0 func() - -func (f fn0) Set(s string) error { - f() - return nil -} - -func (f fn0) Get() interface{} { return nil } - -func (f fn0) String() string { return "" } - -func (f fn0) IsBoolFlag() bool { - return true -} - type fn1 func(string) func (f fn1) Set(s string) error { diff --git a/libgo/go/cmd/internal/objabi/funcdata.go b/libgo/go/cmd/internal/objabi/funcdata.go index 80874edeb0f..a7827125bf6 100644 --- a/libgo/go/cmd/internal/objabi/funcdata.go +++ b/libgo/go/cmd/internal/objabi/funcdata.go @@ -13,9 +13,11 @@ package objabi const ( PCDATA_StackMapIndex = 0 PCDATA_InlTreeIndex = 1 + PCDATA_RegMapIndex = 2 FUNCDATA_ArgsPointerMaps = 0 FUNCDATA_LocalsPointerMaps = 1 FUNCDATA_InlTree = 2 + FUNCDATA_RegPointerMaps = 3 // 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 55f1328ba84..15a63ab8b34 100644 --- a/libgo/go/cmd/internal/objabi/funcid.go +++ b/libgo/go/cmd/internal/objabi/funcid.go @@ -13,6 +13,7 @@ type FuncID uint32 const ( FuncID_normal FuncID = iota // not a special function + FuncID_runtime_main FuncID_goexit FuncID_jmpdefer FuncID_mcall @@ -22,13 +23,11 @@ const ( FuncID_asmcgocall FuncID_sigpanic FuncID_runfinq - FuncID_bgsweep - FuncID_forcegchelper - FuncID_timerproc FuncID_gcBgMarkWorker FuncID_systemstack_switch FuncID_systemstack FuncID_cgocallback_gofunc FuncID_gogo FuncID_externalthreadhandler + FuncID_debugCallV1 ) diff --git a/libgo/go/cmd/internal/objabi/head.go b/libgo/go/cmd/internal/objabi/head.go index ff19606cd2b..23c7b62daf6 100644 --- a/libgo/go/cmd/internal/objabi/head.go +++ b/libgo/go/cmd/internal/objabi/head.go @@ -40,6 +40,7 @@ const ( Hdarwin Hdragonfly Hfreebsd + Hjs Hlinux Hnacl Hnetbsd @@ -57,6 +58,8 @@ func (h *HeadType) Set(s string) error { *h = Hdragonfly case "freebsd": *h = Hfreebsd + case "js": + *h = Hjs case "linux", "android": *h = Hlinux case "nacl": @@ -85,6 +88,8 @@ func (h *HeadType) String() string { return "dragonfly" case Hfreebsd: return "freebsd" + case Hjs: + return "js" case Hlinux: return "linux" case Hnacl: diff --git a/libgo/go/cmd/internal/objabi/reloctype.go b/libgo/go/cmd/internal/objabi/reloctype.go index 2e0b916f7c1..a3e2868a1bc 100644 --- a/libgo/go/cmd/internal/objabi/reloctype.go +++ b/libgo/go/cmd/internal/objabi/reloctype.go @@ -167,7 +167,7 @@ const ( // R_ADDRPOWER_PCREL relocates two D-form instructions like R_ADDRPOWER, but // inserts the displacement from the place being relocated to the address of the - // the relocated symbol instead of just its address. + // relocated symbol instead of just its address. R_ADDRPOWER_PCREL // R_ADDRPOWER_TOCREL relocates two D-form instructions like R_ADDRPOWER, but @@ -176,7 +176,7 @@ const ( R_ADDRPOWER_TOCREL // R_ADDRPOWER_TOCREL relocates a D-form, DS-form instruction sequence like - // R_ADDRPOWER_DS but inserts the offset from the TOC to the address of the the + // R_ADDRPOWER_DS but inserts the offset from the TOC to the address of the // relocated symbol rather than the symbol's address. R_ADDRPOWER_TOCREL_DS @@ -193,6 +193,9 @@ const ( // R_ADDRCUOFF resolves to a pointer-sized offset from the start of the // symbol's DWARF compile unit. R_ADDRCUOFF + + // R_WASMIMPORT resolves to the index of the WebAssembly function import. + R_WASMIMPORT ) // IsDirectJump returns whether r is a relocation for a direct jump. diff --git a/libgo/go/cmd/internal/objabi/reloctype_string.go b/libgo/go/cmd/internal/objabi/reloctype_string.go index a6efe9cad04..2cd3a940454 100644 --- a/libgo/go/cmd/internal/objabi/reloctype_string.go +++ b/libgo/go/cmd/internal/objabi/reloctype_string.go @@ -2,16 +2,16 @@ package objabi -import "fmt" +import "strconv" -const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFF" +const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_WEAKADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_METHODOFFR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_PCRELDBLR_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORT" -var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 129, 136, 144, 152, 160, 166, 172, 178, 188, 197, 208, 219, 229, 238, 251, 265, 279, 293, 309, 323, 337, 348, 362, 377, 394, 412, 433, 443, 454, 467, 478} +var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 60, 66, 72, 81, 92, 101, 112, 122, 129, 136, 144, 152, 160, 166, 172, 178, 188, 197, 208, 219, 229, 238, 251, 265, 279, 293, 309, 323, 337, 348, 362, 377, 394, 412, 433, 443, 454, 467, 478, 490} func (i RelocType) String() string { i -= 1 if i < 0 || i >= RelocType(len(_RelocType_index)-1) { - return fmt.Sprintf("RelocType(%d)", i+1) + return "RelocType(" + strconv.FormatInt(int64(i+1), 10) + ")" } return _RelocType_name[_RelocType_index[i]:_RelocType_index[i+1]] } diff --git a/libgo/go/cmd/internal/objabi/symkind.go b/libgo/go/cmd/internal/objabi/symkind.go index ea180d0bf86..b95a0d3c701 100644 --- a/libgo/go/cmd/internal/objabi/symkind.go +++ b/libgo/go/cmd/internal/objabi/symkind.go @@ -34,6 +34,7 @@ package objabi type SymKind uint8 // Defined SymKind values. +// These are used to index into cmd/link/internal/sym/AbiSymKindToSymKind // // TODO(rsc): Give idiomatic Go names. //go:generate stringer -type=SymKind @@ -58,4 +59,7 @@ const ( SDWARFINFO SDWARFRANGE SDWARFLOC + SDWARFMISC + // Update cmd/link/internal/sym/AbiSymKindToSymKind for new SymKind values. + ) diff --git a/libgo/go/cmd/internal/objabi/symkind_string.go b/libgo/go/cmd/internal/objabi/symkind_string.go index 3064c8ee051..7152d6c0069 100644 --- a/libgo/go/cmd/internal/objabi/symkind_string.go +++ b/libgo/go/cmd/internal/objabi/symkind_string.go @@ -2,15 +2,15 @@ package objabi -import "fmt" +import "strconv" -const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGESDWARFLOC" +const _SymKind_name = "SxxxSTEXTSRODATASNOPTRDATASDATASBSSSNOPTRBSSSTLSBSSSDWARFINFOSDWARFRANGESDWARFLOCSDWARFMISC" -var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 61, 72, 81} +var _SymKind_index = [...]uint8{0, 4, 9, 16, 26, 31, 35, 44, 51, 61, 72, 81, 91} func (i SymKind) String() string { if i >= SymKind(len(_SymKind_index)-1) { - return fmt.Sprintf("SymKind(%d)", i) + return "SymKind(" + strconv.FormatInt(int64(i), 10) + ")" } return _SymKind_name[_SymKind_index[i]:_SymKind_index[i+1]] } diff --git a/libgo/go/cmd/internal/objabi/util.go b/libgo/go/cmd/internal/objabi/util.go index eafef6bfa71..a47e2f93a10 100644 --- a/libgo/go/cmd/internal/objabi/util.go +++ b/libgo/go/cmd/internal/objabi/util.go @@ -21,13 +21,14 @@ func envOr(key, value string) string { var ( defaultGOROOT string // set by linker - GOROOT = envOr("GOROOT", defaultGOROOT) - GOARCH = envOr("GOARCH", defaultGOARCH) - GOOS = envOr("GOOS", defaultGOOS) - GO386 = envOr("GO386", defaultGO386) - GOARM = goarm() - GOMIPS = gomips() - Version = version + GOROOT = envOr("GOROOT", defaultGOROOT) + GOARCH = envOr("GOARCH", defaultGOARCH) + GOOS = envOr("GOOS", defaultGOOS) + GO386 = envOr("GO386", defaultGO386) + GOARM = goarm() + GOMIPS = gomips() + GOMIPS64 = gomips64() + Version = version ) func goarm() int { @@ -53,6 +54,15 @@ func gomips() string { 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 Getgoextlinkenabled() string { return envOr("GO_EXTLINK_ENABLED", defaultGO_EXTLINK_ENABLED) } @@ -95,6 +105,7 @@ var ( Fieldtrack_enabled int Preemptibleloops_enabled int Clobberdead_enabled int + DebugCPU_enabled int ) // Toolchain experiments. @@ -109,6 +120,7 @@ var exper = []struct { {"framepointer", &framepointer_enabled}, {"preemptibleloops", &Preemptibleloops_enabled}, {"clobberdead", &Clobberdead_enabled}, + {"debugcpu", &DebugCPU_enabled}, } var defaultExpstring = Expstring() diff --git a/libgo/go/cmd/internal/test2json/test2json.go b/libgo/go/cmd/internal/test2json/test2json.go index 3e09c8d9151..f8052136be6 100644 --- a/libgo/go/cmd/internal/test2json/test2json.go +++ b/libgo/go/cmd/internal/test2json/test2json.go @@ -16,6 +16,7 @@ import ( "strconv" "strings" "time" + "unicode" "unicode/utf8" ) @@ -140,6 +141,7 @@ var ( []byte("--- PASS: "), []byte("--- FAIL: "), []byte("--- SKIP: "), + []byte("--- BENCH: "), } fourSpace = []byte(" ") @@ -173,6 +175,7 @@ func (c *converter) handleInputLine(line []byte) { // "=== RUN " // "=== PAUSE " // "=== CONT " + actionColon := false origLine := line ok := false indent := 0 @@ -186,6 +189,7 @@ func (c *converter) handleInputLine(line []byte) { // "--- PASS: " // "--- FAIL: " // "--- SKIP: " + // "--- BENCH: " // but possibly indented. for bytes.HasPrefix(line, fourSpace) { line = line[4:] @@ -193,6 +197,7 @@ func (c *converter) handleInputLine(line []byte) { } for _, magic := range reports { if bytes.HasPrefix(line, magic) { + actionColon = true ok = true break } @@ -206,8 +211,15 @@ func (c *converter) handleInputLine(line []byte) { } // Parse out action and test name. - action := strings.ToLower(strings.TrimSuffix(strings.TrimSpace(string(line[4:4+6])), ":")) - name := strings.TrimSpace(string(line[4+6:])) + i := 0 + if actionColon { + i = bytes.IndexByte(line, ':') + 1 + } + if i == 0 { + i = len(updates[0]) + } + action := strings.ToLower(strings.TrimSuffix(strings.TrimSpace(string(line[4:i])), ":")) + name := strings.TrimSpace(string(line[i:])) e := &event{Action: action} if line[0] == '-' { // PASS or FAIL report @@ -226,6 +238,7 @@ func (c *converter) handleInputLine(line []byte) { if len(c.report) < indent { // Nested deeper than expected. // Treat this line as plain output. + c.output.write(origLine) return } // Flush reports at this indentation level or deeper. @@ -342,6 +355,15 @@ func (l *lineBuffer) write(b []byte) { for i < len(l.b) { j := bytes.IndexByte(l.b[i:], '\n') if j < 0 { + if !l.mid { + if j := bytes.IndexByte(l.b[i:], '\t'); j >= 0 { + if isBenchmarkName(bytes.TrimRight(l.b[i:i+j], " ")) { + l.part(l.b[i : i+j+1]) + l.mid = true + i += j + 1 + } + } + } break } e := i + j + 1 @@ -383,6 +405,21 @@ func (l *lineBuffer) flush() { } } +var benchmark = []byte("Benchmark") + +// isBenchmarkName reports whether b is a valid benchmark name +// that might appear as the first field in a benchmark result line. +func isBenchmarkName(b []byte) bool { + if !bytes.HasPrefix(b, benchmark) { + return false + } + if len(b) == len(benchmark) { // just "Benchmark" + return true + } + r, _ := utf8.DecodeRune(b[len(benchmark):]) + return !unicode.IsLower(r) +} + // trimUTF8 returns a length t as close to len(b) as possible such that b[:t] // does not end in the middle of a possibly-valid UTF-8 sequence. // diff --git a/libgo/go/cmd/internal/test2json/testdata/bench.json b/libgo/go/cmd/internal/test2json/testdata/bench.json new file mode 100644 index 00000000000..69e417eb144 --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/bench.json @@ -0,0 +1,14 @@ +{"Action":"output","Output":"goos: darwin\n"} +{"Action":"output","Output":"goarch: 386\n"} +{"Action":"output","Output":"BenchmarkFoo-8 \t2000000000\t 0.00 ns/op\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"--- BENCH: BenchmarkFoo-8\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"output","Test":"BenchmarkFoo-8","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"bench","Test":"BenchmarkFoo-8"} +{"Action":"output","Output":"PASS\n"} +{"Action":"output","Output":"ok \tcommand-line-arguments\t0.009s\n"} +{"Action":"pass"} diff --git a/libgo/go/cmd/internal/test2json/testdata/bench.test b/libgo/go/cmd/internal/test2json/testdata/bench.test new file mode 100644 index 00000000000..453bd5928a5 --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/bench.test @@ -0,0 +1,12 @@ +goos: darwin +goarch: 386 +BenchmarkFoo-8 2000000000 0.00 ns/op +--- BENCH: BenchmarkFoo-8 + x_test.go:8: My benchmark + x_test.go:8: My benchmark + x_test.go:8: My benchmark + x_test.go:8: My benchmark + x_test.go:8: My benchmark + x_test.go:8: My benchmark +PASS +ok command-line-arguments 0.009s diff --git a/libgo/go/cmd/internal/test2json/testdata/benchfail.json b/libgo/go/cmd/internal/test2json/testdata/benchfail.json new file mode 100644 index 00000000000..ad3ac9e179a --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/benchfail.json @@ -0,0 +1,6 @@ +{"Action":"output","Test":"BenchmarkFoo","Output":"--- FAIL: BenchmarkFoo\n"} +{"Action":"output","Test":"BenchmarkFoo","Output":"\tx_test.go:8: My benchmark\n"} +{"Action":"fail","Test":"BenchmarkFoo"} +{"Action":"output","Output":"FAIL\n"} +{"Action":"output","Output":"FAIL\tcommand-line-arguments\t0.008s\n"} +{"Action":"fail"} diff --git a/libgo/go/cmd/internal/test2json/testdata/benchfail.test b/libgo/go/cmd/internal/test2json/testdata/benchfail.test new file mode 100644 index 00000000000..538d9577202 --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/benchfail.test @@ -0,0 +1,4 @@ +--- FAIL: BenchmarkFoo + x_test.go:8: My benchmark +FAIL +FAIL command-line-arguments 0.008s diff --git a/libgo/go/cmd/internal/test2json/testdata/benchshort.json b/libgo/go/cmd/internal/test2json/testdata/benchshort.json new file mode 100644 index 00000000000..8c61d95d8da --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/benchshort.json @@ -0,0 +1,7 @@ +{"Action":"output","Output":"# This file ends in an early EOF to trigger the Benchmark prefix test,\n"} +{"Action":"output","Output":"# which only happens when a benchmark prefix is seen ahead of the \\n.\n"} +{"Action":"output","Output":"# Normally that's due to the benchmark running and the \\n coming later,\n"} +{"Action":"output","Output":"# but to avoid questions of timing, we just use a file with no \\n at all.\n"} +{"Action":"output","Output":"BenchmarkFoo \t"} +{"Action":"output","Output":"10000 early EOF"} +{"Action":"fail"} diff --git a/libgo/go/cmd/internal/test2json/testdata/benchshort.test b/libgo/go/cmd/internal/test2json/testdata/benchshort.test new file mode 100644 index 00000000000..0b173ab20d3 --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/benchshort.test @@ -0,0 +1,5 @@ +# This file ends in an early EOF to trigger the Benchmark prefix test, +# which only happens when a benchmark prefix is seen ahead of the \n. +# Normally that's due to the benchmark running and the \n coming later, +# but to avoid questions of timing, we just use a file with no \n at all. +BenchmarkFoo 10000 early EOF \ No newline at end of file diff --git a/libgo/go/cmd/internal/test2json/testdata/issue23036.json b/libgo/go/cmd/internal/test2json/testdata/issue23036.json new file mode 100644 index 00000000000..935c0c5fc0e --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/issue23036.json @@ -0,0 +1,12 @@ +{"Action":"run","Test":"TestActualCase"} +{"Action":"output","Test":"TestActualCase","Output":"=== RUN TestActualCase\n"} +{"Action":"output","Test":"TestActualCase","Output":"--- FAIL: TestActualCase (0.00s)\n"} +{"Action":"output","Test":"TestActualCase","Output":" foo_test.go:14: Differed.\n"} +{"Action":"output","Test":"TestActualCase","Output":" Expected: MyTest:\n"} +{"Action":"output","Test":"TestActualCase","Output":" --- FAIL: Test output from other tool\n"} +{"Action":"output","Test":"TestActualCase","Output":" Actual: not expected\n"} +{"Action":"fail","Test":"TestActualCase"} +{"Action":"output","Output":"FAIL\n"} +{"Action":"output","Output":"exit status 1\n"} +{"Action":"output","Output":"FAIL github.com/org/project/badtest 0.049s\n"} +{"Action":"fail"} diff --git a/libgo/go/cmd/internal/test2json/testdata/issue23036.test b/libgo/go/cmd/internal/test2json/testdata/issue23036.test new file mode 100644 index 00000000000..fd4774f4b63 --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/issue23036.test @@ -0,0 +1,9 @@ +=== RUN TestActualCase +--- FAIL: TestActualCase (0.00s) + foo_test.go:14: Differed. + Expected: MyTest: + --- FAIL: Test output from other tool + Actual: not expected +FAIL +exit status 1 +FAIL github.com/org/project/badtest 0.049s diff --git a/libgo/go/cmd/internal/test2json/testdata/issue23920.json b/libgo/go/cmd/internal/test2json/testdata/issue23920.json new file mode 100644 index 00000000000..28f7bd56ac3 --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/issue23920.json @@ -0,0 +1,14 @@ +{"Action":"run","Test":"TestWithColons"} +{"Action":"output","Test":"TestWithColons","Output":"=== RUN TestWithColons\n"} +{"Action":"run","Test":"TestWithColons/[::1]"} +{"Action":"output","Test":"TestWithColons/[::1]","Output":"=== RUN TestWithColons/[::1]\n"} +{"Action":"run","Test":"TestWithColons/127.0.0.1:0"} +{"Action":"output","Test":"TestWithColons/127.0.0.1:0","Output":"=== RUN TestWithColons/127.0.0.1:0\n"} +{"Action":"output","Test":"TestWithColons","Output":"--- PASS: TestWithColons (0.00s)\n"} +{"Action":"output","Test":"TestWithColons/[::1]","Output":" --- PASS: TestWithColons/[::1] (0.00s)\n"} +{"Action":"pass","Test":"TestWithColons/[::1]"} +{"Action":"output","Test":"TestWithColons/127.0.0.1:0","Output":" --- PASS: TestWithColons/127.0.0.1:0 (0.00s)\n"} +{"Action":"pass","Test":"TestWithColons/127.0.0.1:0"} +{"Action":"pass","Test":"TestWithColons"} +{"Action":"output","Output":"PASS\n"} +{"Action":"pass"} diff --git a/libgo/go/cmd/internal/test2json/testdata/issue23920.test b/libgo/go/cmd/internal/test2json/testdata/issue23920.test new file mode 100644 index 00000000000..43bf0580343 --- /dev/null +++ b/libgo/go/cmd/internal/test2json/testdata/issue23920.test @@ -0,0 +1,7 @@ +=== RUN TestWithColons +=== RUN TestWithColons/[::1] +=== RUN TestWithColons/127.0.0.1:0 +--- PASS: TestWithColons (0.00s) + --- PASS: TestWithColons/[::1] (0.00s) + --- PASS: TestWithColons/127.0.0.1:0 (0.00s) +PASS diff --git a/libgo/go/cmd/test2json/main.go b/libgo/go/cmd/test2json/main.go index 7bdc867bbe5..0385d8f246c 100644 --- a/libgo/go/cmd/test2json/main.go +++ b/libgo/go/cmd/test2json/main.go @@ -45,15 +45,17 @@ // pause - the test has been paused // cont - the test has continued running // pass - the test passed -// fail - the test failed +// bench - the benchmark printed log output but did not fail +// fail - the test or benchmark failed // output - the test printed output +// skip - the test was skipped or the package contained no tests // // The Package field, if present, specifies the package being tested. // When the go command runs parallel tests in -json mode, events from // different tests are interlaced; the Package field allows readers to // separate them. // -// The Test field, if present, specifies the test or example, or benchmark +// The Test field, if present, specifies the test, example, or benchmark // function that caused the event. Events for the overall package test // do not set Test. // @@ -67,6 +69,14 @@ // the concatenation of the Output fields of all output events is the exact // output of the test execution. // +// When a benchmark runs, it typically produces a single line of output +// giving timing results. That line is reported in an event with Action == "output" +// and no Test field. If a benchmark logs output or reports a failure +// (for example, by using b.Log or b.Error), that extra output is reported +// as a sequence of events with Test set to the benchmark name, terminated +// by a final event with Action == "bench" or "fail". +// Benchmarks have no events with Action == "run", "pause", or "cont". +// package main import ( diff --git a/libgo/go/cmd/vet/all/main.go b/libgo/go/cmd/vet/all/main.go index 09167af6d53..09181f96895 100644 --- a/libgo/go/cmd/vet/all/main.go +++ b/libgo/go/cmd/vet/all/main.go @@ -192,6 +192,12 @@ func vetPlatforms(pp []platform) { } func (p platform) vet() { + if p.os == "linux" && p.arch == "riscv64" { + // TODO(tklauser): enable as soon as the riscv64 port has fully landed + fmt.Println("skipping linux/riscv64") + return + } + var buf bytes.Buffer fmt.Fprintf(&buf, "go run main.go -p %s\n", p) diff --git a/libgo/go/cmd/vet/all/whitelist/386.txt b/libgo/go/cmd/vet/all/whitelist/386.txt index 505856f3686..f59094eb14f 100644 --- a/libgo/go/cmd/vet/all/whitelist/386.txt +++ b/libgo/go/cmd/vet/all/whitelist/386.txt @@ -1,6 +1,7 @@ // 386-specific vet whitelist. See readme.txt for details. -runtime/asm_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_386.s: [386] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_386.s: [386] cannot check cross-package assembly function: cmpstring is in package runtime // startup code uses non-standard calling convention and intentionally // omits args. @@ -15,13 +16,9 @@ runtime/asm_386.s: [386] morestack: use of 4(SP) points beyond argument frame runtime/asm_386.s: [386] ldt0setup: function ldt0setup missing Go declaration runtime/asm_386.s: [386] emptyfunc: function emptyfunc missing Go declaration runtime/asm_386.s: [386] aeshashbody: function aeshashbody missing Go declaration -runtime/asm_386.s: [386] memeqbody: function memeqbody missing Go declaration -runtime/asm_386.s: [386] cmpbody: function cmpbody missing Go declaration runtime/asm_386.s: [386] addmoduledata: function addmoduledata missing Go declaration runtime/duff_386.s: [386] duffzero: function duffzero missing Go declaration runtime/duff_386.s: [386] duffcopy: function duffcopy missing Go declaration runtime/asm_386.s: [386] uint32tofloat64: function uint32tofloat64 missing Go declaration runtime/asm_386.s: [386] float64touint32: function float64touint32 missing Go declaration - -runtime/asm_386.s: [386] stackcheck: function stackcheck missing Go declaration diff --git a/libgo/go/cmd/vet/all/whitelist/all.txt b/libgo/go/cmd/vet/all/whitelist/all.txt index 6792d263a5e..397ee4e9875 100644 --- a/libgo/go/cmd/vet/all/whitelist/all.txt +++ b/libgo/go/cmd/vet/all/whitelist/all.txt @@ -11,9 +11,14 @@ go/types/scope.go: method WriteTo(w io.Writer, n int, recurse bool) should have // Nothing much to do about cross-package assembly. Unfortunate. runtime/asm_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: call is in package reflect -runtime/asm_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: Equal is in package bytes -runtime/asm_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: IndexByte is in package bytes -runtime/asm_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: IndexByte is in package strings +internal/bytealg/equal_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: Equal is in package bytes +internal/bytealg/equal_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: memequal is in package runtime +internal/bytealg/equal_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: memequal_varlen is in package runtime +internal/bytealg/indexbyte_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: IndexByte is in package bytes +internal/bytealg/indexbyte_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: IndexByte is in package strings + +// The write barrier is called directly by the compiler, so no Go def +runtime/asm_ARCHSUFF.s: [GOARCH] gcWriteBarrier: function gcWriteBarrier missing Go declaration // Legitimate vet complaints in which we are testing for correct runtime behavior // in bad situations that vet can also detect statically. @@ -22,7 +27,6 @@ encoding/json/decode_test.go: struct field m2 has json tag but is not exported encoding/json/tagkey_test.go: struct field tag `:"BadFormat"` not compatible with reflect.StructTag.Get: bad syntax for struct tag key runtime/testdata/testprog/deadlock.go: unreachable code runtime/testdata/testprog/deadlock.go: unreachable code -sync/cond_test.go: assignment copies lock value to c2: sync.Cond contains sync.noCopy // Non-standard method signatures. // These cases are basically ok. diff --git a/libgo/go/cmd/vet/all/whitelist/amd64.txt b/libgo/go/cmd/vet/all/whitelist/amd64.txt index ebde7be58b0..20e0d48d532 100644 --- a/libgo/go/cmd/vet/all/whitelist/amd64.txt +++ b/libgo/go/cmd/vet/all/whitelist/amd64.txt @@ -1,34 +1,22 @@ // amd64-specific vet whitelist. See readme.txt for details. - // False positives. +// Nothing much to do about cross-package assembly. Unfortunate. +internal/bytealg/compare_amd64.s: [amd64] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_amd64.s: [amd64] cannot check cross-package assembly function: cmpstring is in package runtime // reflect trampolines intentionally omit arg size. Same for morestack. runtime/asm_amd64.s: [amd64] morestack: use of 8(SP) points beyond argument frame runtime/asm_amd64.s: [amd64] morestack: use of 16(SP) points beyond argument frame runtime/asm_amd64.s: [amd64] morestack: use of 8(SP) points beyond argument frame -// Nothing much to do about cross-package assembly. Unfortunate. -runtime/asm_amd64.s: [amd64] cannot check cross-package assembly function: indexShortStr is in package strings -runtime/asm_amd64.s: [GOARCH] cannot check cross-package assembly function: Compare is in package bytes -runtime/asm_amd64.s: [amd64] cannot check cross-package assembly function: indexShortStr is in package bytes -runtime/asm_amd64.s: [amd64] cannot check cross-package assembly function: countByte is in package strings -runtime/asm_amd64.s: [amd64] cannot check cross-package assembly function: countByte is in package bytes - // Intentionally missing declarations. These are special assembly routines. // Some are jumped into from other routines, with values in specific registers. // duff* have direct calls from the compiler. // Others use the platform ABI. // There is no sensible corresponding Go prototype. runtime/asm_amd64.s: [amd64] aeshashbody: function aeshashbody missing Go declaration -runtime/asm_amd64.s: [amd64] memeqbody: function memeqbody missing Go declaration -runtime/asm_amd64.s: [amd64] cmpbody: function cmpbody missing Go declaration -runtime/asm_amd64.s: [amd64] indexbytebody: function indexbytebody missing Go declaration runtime/asm_amd64.s: [amd64] addmoduledata: function addmoduledata missing Go declaration runtime/duff_amd64.s: [amd64] duffzero: function duffzero missing Go declaration runtime/duff_amd64.s: [amd64] duffcopy: function duffcopy missing Go declaration -runtime/asm_amd64.s: [amd64] stackcheck: function stackcheck missing Go declaration -runtime/asm_amd64.s: [amd64] indexShortStr: function indexShortStr missing Go declaration -runtime/asm_amd64.s: [amd64] countByte: function countByte missing Go declaration -runtime/asm_amd64.s: [amd64] gcWriteBarrier: function gcWriteBarrier missing Go declaration diff --git a/libgo/go/cmd/vet/all/whitelist/arm.txt b/libgo/go/cmd/vet/all/whitelist/arm.txt index 839346c2d49..8f98782f940 100644 --- a/libgo/go/cmd/vet/all/whitelist/arm.txt +++ b/libgo/go/cmd/vet/all/whitelist/arm.txt @@ -1,15 +1,11 @@ // arm-specific vet whitelist. See readme.txt for details. -runtime/asm_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: Compare is in package bytes - -// reflect trampolines intentionally omit arg size. Same for morestack. -runtime/asm_arm.s: [arm] morestack: use of 4(R13) points beyond argument frame +internal/bytealg/compare_arm.s: [arm] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_arm.s: [arm] cannot check cross-package assembly function: cmpstring is in package runtime // Intentionally missing declarations. runtime/asm_arm.s: [arm] emptyfunc: function emptyfunc missing Go declaration -runtime/asm_arm.s: [arm] abort: function abort missing Go declaration runtime/asm_arm.s: [arm] armPublicationBarrier: function armPublicationBarrier missing Go declaration -runtime/asm_arm.s: [arm] cmpbody: function cmpbody missing Go declaration runtime/asm_arm.s: [arm] usplitR0: function usplitR0 missing Go declaration runtime/asm_arm.s: [arm] addmoduledata: function addmoduledata missing Go declaration runtime/duff_arm.s: [arm] duffzero: function duffzero missing Go declaration diff --git a/libgo/go/cmd/vet/all/whitelist/arm64.txt b/libgo/go/cmd/vet/all/whitelist/arm64.txt index 24fc6f42235..ee0292b4152 100644 --- a/libgo/go/cmd/vet/all/whitelist/arm64.txt +++ b/libgo/go/cmd/vet/all/whitelist/arm64.txt @@ -1,9 +1,9 @@ // arm64-specific vet whitelist. See readme.txt for details. -runtime/asm_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_arm64.s: [arm64] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_arm64.s: [arm64] cannot check cross-package assembly function: cmpstring is in package runtime // Intentionally missing declarations. -runtime/asm_arm64.s: [arm64] abort: function abort missing Go declaration runtime/asm_arm64.s: [arm64] addmoduledata: function addmoduledata missing Go declaration runtime/duff_arm64.s: [arm64] duffzero: function duffzero missing Go declaration runtime/duff_arm64.s: [arm64] duffcopy: function duffcopy missing Go declaration diff --git a/libgo/go/cmd/vet/all/whitelist/darwin_386.txt b/libgo/go/cmd/vet/all/whitelist/darwin_386.txt index d19d7d7bd04..5c25e092f20 100644 --- a/libgo/go/cmd/vet/all/whitelist/darwin_386.txt +++ b/libgo/go/cmd/vet/all/whitelist/darwin_386.txt @@ -2,8 +2,4 @@ // Ok -runtime/sys_darwin_386.s: [386] now: function now missing Go declaration -runtime/sys_darwin_386.s: [386] bsdthread_start: function bsdthread_start missing Go declaration -runtime/sys_darwin_386.s: [386] sysenter: function sysenter missing Go declaration runtime/sys_darwin_386.s: [386] setldt: function setldt missing Go declaration -runtime/sys_darwin_386.s: [386] cannot check cross-package assembly function: now is in package time diff --git a/libgo/go/cmd/vet/all/whitelist/darwin_amd64.txt b/libgo/go/cmd/vet/all/whitelist/darwin_amd64.txt index 94a4e8fa75b..fcdacb2dc1b 100644 --- a/libgo/go/cmd/vet/all/whitelist/darwin_amd64.txt +++ b/libgo/go/cmd/vet/all/whitelist/darwin_amd64.txt @@ -1,5 +1,3 @@ // darwin/amd64-specific vet whitelist. See readme.txt for details. -runtime/sys_darwin_amd64.s: [amd64] bsdthread_start: function bsdthread_start missing Go declaration runtime/sys_darwin_amd64.s: [amd64] settls: function settls missing Go declaration -runtime/sys_darwin_amd64.s: [amd64] cannot check cross-package assembly function: now is in package time diff --git a/libgo/go/cmd/vet/all/whitelist/darwin_arm.txt b/libgo/go/cmd/vet/all/whitelist/darwin_arm.txt index 0e619be4623..1c25c6a9397 100644 --- a/libgo/go/cmd/vet/all/whitelist/darwin_arm.txt +++ b/libgo/go/cmd/vet/all/whitelist/darwin_arm.txt @@ -1,12 +1,5 @@ // darwin/arm-specific vet whitelist. See readme.txt for details. -// False positives due to comments in assembly. -// To be removed. See CL 27154. - -runtime/sys_darwin_arm.s: [arm] sigfwd: use of unnamed argument 0(FP); offset 0 is fn+0(FP) - - // Ok. -runtime/sys_darwin_arm.s: [arm] bsdthread_start: function bsdthread_start missing Go declaration runtime/asm_arm.s: [arm] sigreturn: function sigreturn missing Go declaration diff --git a/libgo/go/cmd/vet/all/whitelist/darwin_arm64.txt b/libgo/go/cmd/vet/all/whitelist/darwin_arm64.txt index 793cccf8dd8..a1edb713832 100644 --- a/libgo/go/cmd/vet/all/whitelist/darwin_arm64.txt +++ b/libgo/go/cmd/vet/all/whitelist/darwin_arm64.txt @@ -1,8 +1,3 @@ // darwin/arm64-specific vet whitelist. See readme.txt for details. -runtime/sys_darwin_arm64.s: [arm64] sigtramp: 24(RSP) should be infostyle+8(FP) -runtime/sys_darwin_arm64.s: [arm64] sigtramp: 24(RSP) should be infostyle+8(FP) -runtime/sys_darwin_arm64.s: [arm64] bsdthread_create: RET without writing to 4-byte ret+24(FP) -runtime/sys_darwin_arm64.s: [arm64] bsdthread_start: function bsdthread_start missing Go declaration -runtime/sys_darwin_arm64.s: [arm64] bsdthread_register: RET without writing to 4-byte ret+0(FP) runtime/asm_arm64.s: [arm64] sigreturn: function sigreturn missing Go declaration diff --git a/libgo/go/cmd/vet/all/whitelist/linux_ppc64x.txt b/libgo/go/cmd/vet/all/whitelist/linux_ppc64x.txt index 21e87e37d8c..0091d97110b 100644 --- a/libgo/go/cmd/vet/all/whitelist/linux_ppc64x.txt +++ b/libgo/go/cmd/vet/all/whitelist/linux_ppc64x.txt @@ -2,4 +2,3 @@ runtime/sys_linux_ppc64x.s: [GOARCH] _sigtramp: function _sigtramp missing Go declaration runtime/sys_linux_ppc64x.s: [GOARCH] _cgoSigtramp: function _cgoSigtramp missing Go declaration -runtime/asm_ppc64x.s: [GOARCH] procyield: use of 24(R1) points beyond argument frame diff --git a/libgo/go/cmd/vet/all/whitelist/mips.txt b/libgo/go/cmd/vet/all/whitelist/mips.txt index ad29336ad1b..fa17c6233b2 100644 --- a/libgo/go/cmd/vet/all/whitelist/mips.txt +++ b/libgo/go/cmd/vet/all/whitelist/mips.txt @@ -1,4 +1,4 @@ -// mips64-specific vet whitelist. See readme.txt for details. +// mips-specific (big endian) vet whitelist. See readme.txt for details. // Work around if-def'd code. Will be fixed by golang.org/issue/17544. runtime/sys_linux_mipsx.s: [mips] walltime: invalid offset sec_lo+0(FP); expected sec_lo+4(FP) diff --git a/libgo/go/cmd/vet/all/whitelist/mips64x.txt b/libgo/go/cmd/vet/all/whitelist/mips64x.txt index 5354d21c642..16877654458 100644 --- a/libgo/go/cmd/vet/all/whitelist/mips64x.txt +++ b/libgo/go/cmd/vet/all/whitelist/mips64x.txt @@ -1,6 +1,5 @@ // mips64-specific vet whitelist. See readme.txt for details. -runtime/asm_mips64x.s: [GOARCH] abort: function abort missing Go declaration runtime/duff_mips64x.s: [GOARCH] duffzero: function duffzero missing Go declaration runtime/tls_mips64x.s: [GOARCH] save_g: function save_g missing Go declaration runtime/tls_mips64x.s: [GOARCH] load_g: function load_g missing Go declaration diff --git a/libgo/go/cmd/vet/all/whitelist/mipsle.txt b/libgo/go/cmd/vet/all/whitelist/mipsle.txt index 929216905e6..9361dc43537 100644 --- a/libgo/go/cmd/vet/all/whitelist/mipsle.txt +++ b/libgo/go/cmd/vet/all/whitelist/mipsle.txt @@ -1,4 +1,4 @@ -// mips64-specific vet whitelist. See readme.txt for details. +// mipsle-specific vet whitelist. See readme.txt for details. // Work around if-def'd code. Will be fixed by golang.org/issue/17544. runtime/sys_linux_mipsx.s: [mipsle] walltime: invalid offset sec_lo+4(FP); expected sec_lo+0(FP) diff --git a/libgo/go/cmd/vet/all/whitelist/mipsx.txt b/libgo/go/cmd/vet/all/whitelist/mipsx.txt index 860f8399211..1a2cd3ff624 100644 --- a/libgo/go/cmd/vet/all/whitelist/mipsx.txt +++ b/libgo/go/cmd/vet/all/whitelist/mipsx.txt @@ -1,9 +1,10 @@ -// mips64-specific vet whitelist. See readme.txt for details. +// mips/mipsle-specific vet whitelist. See readme.txt for details. + +internal/bytealg/compare_mipsx.s: [GOARCH] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_mipsx.s: [GOARCH] cannot check cross-package assembly function: cmpstring is in package runtime -runtime/asm_mipsx.s: [GOARCH] abort: function abort missing Go declaration runtime/tls_mipsx.s: [GOARCH] save_g: function save_g missing Go declaration runtime/tls_mipsx.s: [GOARCH] load_g: function load_g missing Go declaration -runtime/asm_mipsx.s: [GOARCH] cannot check cross-package assembly function: Compare is in package bytes runtime/sys_linux_mipsx.s: [GOARCH] clone: 12(R29) should be mp+8(FP) runtime/sys_linux_mipsx.s: [GOARCH] clone: 4(R29) should be flags+0(FP) runtime/sys_linux_mipsx.s: [GOARCH] clone: 8(R29) should be stk+4(FP) diff --git a/libgo/go/cmd/vet/all/whitelist/nacl_amd64p32.txt b/libgo/go/cmd/vet/all/whitelist/nacl_amd64p32.txt index 4b2aad2aacd..1ec11f7ca87 100644 --- a/libgo/go/cmd/vet/all/whitelist/nacl_amd64p32.txt +++ b/libgo/go/cmd/vet/all/whitelist/nacl_amd64p32.txt @@ -1,5 +1,8 @@ // nacl/amd64p32-specific vet whitelist. See readme.txt for details. +internal/bytealg/compare_amd64p32.s: [amd64p32] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_amd64p32.s: [amd64p32] cannot check cross-package assembly function: cmpstring is in package runtime + // reflect trampolines intentionally omit arg size. Same for morestack. runtime/asm_amd64p32.s: [amd64p32] morestack: use of 8(SP) points beyond argument frame runtime/asm_amd64p32.s: [amd64p32] morestack: use of 16(SP) points beyond argument frame @@ -20,10 +23,4 @@ runtime/sys_nacl_amd64p32.s: [amd64p32] settls: function settls missing Go decla runtime/asm_amd64p32.s: [amd64p32] rt0_go: unknown variable argc runtime/asm_amd64p32.s: [amd64p32] rt0_go: unknown variable argv -runtime/asm_amd64p32.s: [amd64p32] memeqbody: function memeqbody missing Go declaration -runtime/asm_amd64p32.s: [amd64p32] cannot check cross-package assembly function: Compare is in package bytes -runtime/asm_amd64p32.s: [amd64p32] cmpbody: function cmpbody missing Go declaration -runtime/asm_amd64p32.s: [amd64p32] indexbytebody: function indexbytebody missing Go declaration runtime/asm_amd64p32.s: [amd64p32] asmcgocall: RET without writing to 4-byte ret+8(FP) - -runtime/asm_amd64p32.s: [amd64p32] stackcheck: function stackcheck missing Go declaration diff --git a/libgo/go/cmd/vet/all/whitelist/ppc64x.txt b/libgo/go/cmd/vet/all/whitelist/ppc64x.txt index 4f6444e1026..65a904ed481 100644 --- a/libgo/go/cmd/vet/all/whitelist/ppc64x.txt +++ b/libgo/go/cmd/vet/all/whitelist/ppc64x.txt @@ -1,10 +1,9 @@ // ppc64-specific vet whitelist. See readme.txt for details. -runtime/asm_ARCHSUFF.s: [GOARCH] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_ppc64x.s: [GOARCH] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_ppc64x.s: [GOARCH] cannot check cross-package assembly function: cmpstring is in package runtime runtime/asm_ppc64x.s: [GOARCH] reginit: function reginit missing Go declaration -runtime/asm_ppc64x.s: [GOARCH] abort: function abort missing Go declaration -runtime/asm_ppc64x.s: [GOARCH] memeqbody: function memeqbody missing Go declaration runtime/asm_ppc64x.s: [GOARCH] goexit: use of 24(R1) points beyond argument frame runtime/asm_ppc64x.s: [GOARCH] addmoduledata: function addmoduledata missing Go declaration runtime/duff_ppc64x.s: [GOARCH] duffzero: function duffzero missing Go declaration diff --git a/libgo/go/cmd/vet/all/whitelist/s390x.txt b/libgo/go/cmd/vet/all/whitelist/s390x.txt index f18236c4f11..5bc48e5afcf 100644 --- a/libgo/go/cmd/vet/all/whitelist/s390x.txt +++ b/libgo/go/cmd/vet/all/whitelist/s390x.txt @@ -1,17 +1,14 @@ -runtime/asm_s390x.s: [s390x] abort: function abort missing Go declaration -runtime/asm_s390x.s: [s390x] memeqbody: function memeqbody missing Go declaration -runtime/asm_s390x.s: [s390x] memeqbodyclc: function memeqbodyclc missing Go declaration -runtime/asm_s390x.s: [s390x] indexbytebody: function indexbytebody missing Go declaration -runtime/asm_s390x.s: [s390x] cannot check cross-package assembly function: Compare is in package bytes -runtime/asm_s390x.s: [s390x] cmpbody: function cmpbody missing Go declaration -runtime/asm_s390x.s: [s390x] cmpbodyclc: function cmpbodyclc missing Go declaration -runtime/asm_s390x.s: [s390x] cannot check cross-package assembly function: supportsVX is in package strings -runtime/asm_s390x.s: [s390x] cannot check cross-package assembly function: supportsVX is in package bytes -runtime/asm_s390x.s: [s390x] cannot check cross-package assembly function: indexShortStr is in package strings -runtime/asm_s390x.s: [s390x] cannot check cross-package assembly function: indexShortStr is in package bytes -runtime/asm_s390x.s: [s390x] indexShortStr: function indexShortStr missing Go declaration +internal/bytealg/compare_s390x.s: [s390x] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_s390x.s: [s390x] cannot check cross-package assembly function: cmpstring is in package runtime runtime/asm_s390x.s: [s390x] addmoduledata: function addmoduledata missing Go declaration runtime/memclr_s390x.s: [s390x] memclr_s390x_exrl_xc: function memclr_s390x_exrl_xc missing Go declaration runtime/memmove_s390x.s: [s390x] memmove_s390x_exrl_mvc: function memmove_s390x_exrl_mvc missing Go declaration runtime/tls_s390x.s: [s390x] save_g: function save_g missing Go declaration runtime/tls_s390x.s: [s390x] load_g: function load_g missing Go declaration +internal/cpu/cpu_s390x.s: [s390x] stfle: invalid MOVD of ret+0(FP); cpu.facilityList is 32-byte value +internal/cpu/cpu_s390x.s: [s390x] kmQuery: invalid MOVD of ret+0(FP); cpu.queryResult is 16-byte value +internal/cpu/cpu_s390x.s: [s390x] kmcQuery: invalid MOVD of ret+0(FP); cpu.queryResult is 16-byte value +internal/cpu/cpu_s390x.s: [s390x] kmctrQuery: invalid MOVD of ret+0(FP); cpu.queryResult is 16-byte value +internal/cpu/cpu_s390x.s: [s390x] kmaQuery: invalid MOVD of ret+0(FP); cpu.queryResult is 16-byte value +internal/cpu/cpu_s390x.s: [s390x] kimdQuery: invalid MOVD of ret+0(FP); cpu.queryResult is 16-byte value +internal/cpu/cpu_s390x.s: [s390x] klmdQuery: invalid MOVD of ret+0(FP); cpu.queryResult is 16-byte value diff --git a/libgo/go/cmd/vet/all/whitelist/wasm.txt b/libgo/go/cmd/vet/all/whitelist/wasm.txt new file mode 100644 index 00000000000..7a8037f085e --- /dev/null +++ b/libgo/go/cmd/vet/all/whitelist/wasm.txt @@ -0,0 +1,28 @@ +// wasm-specific vet whitelist. See readme.txt for details. + +// False positives. + +// Nothing much to do about cross-package assembly. Unfortunate. +internal/bytealg/compare_wasm.s: [wasm] cannot check cross-package assembly function: Compare is in package bytes +internal/bytealg/compare_wasm.s: [wasm] cannot check cross-package assembly function: cmpstring is in package runtime + +// morestack intentionally omits arg size. +runtime/asm_wasm.s: [wasm] morestack: use of 8(SP) points beyond argument frame +runtime/asm_wasm.s: [wasm] morestack: use of 16(SP) points beyond argument frame +runtime/asm_wasm.s: [wasm] morestack: use of 8(SP) points beyond argument frame + +// rt0_go does not allocate a stack frame. +runtime/asm_wasm.s: [wasm] rt0_go: use of 8(SP) points beyond argument frame + +// Calling WebAssembly import. No write from Go assembly. +runtime/sys_wasm.s: [wasm] nanotime: RET without writing to 8-byte ret+0(FP) +runtime/sys_wasm.s: [wasm] scheduleCallback: RET without writing to 4-byte ret+8(FP) +syscall/js/js_js.s: [wasm] stringVal: RET without writing to 8-byte ret+16(FP) +syscall/js/js_js.s: [wasm] valueGet: RET without writing to 8-byte ret+24(FP) +syscall/js/js_js.s: [wasm] valueIndex: RET without writing to 8-byte ret+16(FP) +syscall/js/js_js.s: [wasm] valueCall: RET without writing to 8-byte ret+48(FP) +syscall/js/js_js.s: [wasm] valueInvoke: RET without writing to 8-byte ret+32(FP) +syscall/js/js_js.s: [wasm] valueNew: RET without writing to 8-byte ret+32(FP) +syscall/js/js_js.s: [wasm] valueLength: RET without writing to 8-byte ret+8(FP) +syscall/js/js_js.s: [wasm] valuePrepareString: RET without writing to 8-byte ret+8(FP) +syscall/js/js_js.s: [wasm] valueInstanceOf: RET without writing to 1-byte ret+16(FP) diff --git a/libgo/go/cmd/vet/asmdecl.go b/libgo/go/cmd/vet/asmdecl.go index b01d23d342b..ccf6269f1db 100644 --- a/libgo/go/cmd/vet/asmdecl.go +++ b/libgo/go/cmd/vet/asmdecl.go @@ -77,6 +77,7 @@ var ( asmArchPpc64 = asmArch{name: "ppc64", bigEndian: true, stack: "R1", lr: true} asmArchPpc64LE = asmArch{name: "ppc64le", bigEndian: false, stack: "R1", lr: true} asmArchS390X = asmArch{name: "s390x", bigEndian: true, stack: "R15", lr: true} + asmArchWasm = asmArch{name: "wasm", bigEndian: false, stack: "SP", lr: false} arches = []*asmArch{ &asmArch386, @@ -91,6 +92,7 @@ var ( &asmArchPpc64, &asmArchPpc64LE, &asmArchS390X, + &asmArchWasm, } ) @@ -104,6 +106,8 @@ func init() { arch.ptrSize = int(arch.sizes.Sizeof(types.Typ[types.UnsafePointer])) arch.maxAlign = int(arch.sizes.Alignof(types.Typ[types.Int64])) } + + registerPkgCheck("asmdecl", asmCheck) } var ( @@ -119,7 +123,7 @@ var ( ) func asmCheck(pkg *Package) { - if !vet("asmdecl") { + if vcfg.VetxOnly { return } @@ -240,17 +244,17 @@ Files: continue } } + flag := m[3] fn = knownFunc[fnName][arch] if fn != nil { size, _ := strconv.Atoi(m[5]) - flag := m[3] if size != fn.size && (flag != "7" && !strings.Contains(flag, "NOSPLIT") || size != 0) { badf("wrong argument size %d; expected $...-%d", size, fn.size) } } localSize, _ = strconv.Atoi(m[4]) localSize += archDef.intSize - if archDef.lr { + if archDef.lr && !strings.Contains(flag, "NOFRAME") { // Account for caller's saved LR localSize += archDef.intSize } diff --git a/libgo/go/cmd/vet/assign.go b/libgo/go/cmd/vet/assign.go index bfa5b303293..223e80d4007 100644 --- a/libgo/go/cmd/vet/assign.go +++ b/libgo/go/cmd/vet/assign.go @@ -37,7 +37,7 @@ func checkAssignStmt(f *File, node ast.Node) { } for i, lhs := range stmt.Lhs { rhs := stmt.Rhs[i] - if hasSideEffects(lhs) || hasSideEffects(rhs) { + if hasSideEffects(f, lhs) || hasSideEffects(f, rhs) { continue // expressions may not be equal } if reflect.TypeOf(lhs) != reflect.TypeOf(rhs) { diff --git a/libgo/go/cmd/vet/atomic.go b/libgo/go/cmd/vet/atomic.go index b2ca2d80f30..b425669e1ae 100644 --- a/libgo/go/cmd/vet/atomic.go +++ b/libgo/go/cmd/vet/atomic.go @@ -7,6 +7,7 @@ package main import ( "go/ast" "go/token" + "go/types" ) func init() { @@ -36,8 +37,9 @@ func checkAtomicAssignment(f *File, node ast.Node) { if !ok { continue } - pkg, ok := sel.X.(*ast.Ident) - if !ok || pkg.Name != "atomic" { + pkgIdent, _ := sel.X.(*ast.Ident) + pkgName, ok := f.pkg.uses[pkgIdent].(*types.PkgName) + if !ok || pkgName.Imported().Path() != "sync/atomic" { continue } diff --git a/libgo/go/cmd/vet/bool.go b/libgo/go/cmd/vet/bool.go index 07c2a93dffa..1cd477f988c 100644 --- a/libgo/go/cmd/vet/bool.go +++ b/libgo/go/cmd/vet/bool.go @@ -31,7 +31,7 @@ func checkBool(f *File, n ast.Node) { return } - comm := op.commutativeSets(e) + comm := op.commutativeSets(f, e) for _, exprs := range comm { op.checkRedundant(f, exprs) op.checkSuspect(f, exprs) @@ -53,14 +53,14 @@ var ( // expressions in e that are connected by op. // For example, given 'a || b || f() || c || d' with the or op, // commutativeSets returns {{b, a}, {d, c}}. -func (op boolOp) commutativeSets(e *ast.BinaryExpr) [][]ast.Expr { +func (op boolOp) commutativeSets(f *File, e *ast.BinaryExpr) [][]ast.Expr { exprs := op.split(e) // Partition the slice of expressions into commutative sets. i := 0 var sets [][]ast.Expr for j := 0; j <= len(exprs); j++ { - if j == len(exprs) || hasSideEffects(exprs[j]) { + if j == len(exprs) || hasSideEffects(f, exprs[j]) { if i < j { sets = append(sets, exprs[i:j]) } @@ -136,16 +136,27 @@ func (op boolOp) checkSuspect(f *File, exprs []ast.Expr) { } // hasSideEffects reports whether evaluation of e has side effects. -func hasSideEffects(e ast.Expr) bool { +func hasSideEffects(f *File, e ast.Expr) bool { safe := true ast.Inspect(e, func(node ast.Node) bool { switch n := node.(type) { - // Using CallExpr here will catch conversions - // as well as function and method invocations. - // We'll live with the false negatives for now. case *ast.CallExpr: - safe = false - return false + typVal := f.pkg.types[n.Fun] + switch { + case typVal.IsType(): + // Type conversion, which is safe. + case typVal.IsBuiltin(): + // Builtin func, conservatively assumed to not + // be safe for now. + safe = false + return false + default: + // A non-builtin func or method call. + // Conservatively assume that all of them have + // side effects for now. + safe = false + return false + } case *ast.UnaryExpr: if n.Op == token.ARROW { safe = false diff --git a/libgo/go/cmd/vet/buildtag.go b/libgo/go/cmd/vet/buildtag.go index 80d8f819240..ba3a361b911 100644 --- a/libgo/go/cmd/vet/buildtag.go +++ b/libgo/go/cmd/vet/buildtag.go @@ -18,12 +18,39 @@ var ( plusBuild = []byte("+build") ) +func badfLine(f *File, line int, format string, args ...interface{}) { + msg := fmt.Sprintf(format, args...) + fmt.Fprintf(os.Stderr, "%s:%d: %s\n", f.name, line, msg) + setExit(1) +} + // checkBuildTag checks that build tags are in the correct location and well-formed. -func checkBuildTag(name string, data []byte) { +func checkBuildTag(f *File) { if !vet("buildtags") { return } - lines := bytes.SplitAfter(data, nl) + + // we must look at the raw lines, as build tags may appear in non-Go + // files such as assembly files. + lines := bytes.SplitAfter(f.content, nl) + + // lineWithComment reports whether a line corresponds to a comment in + // the source file. If the source file wasn't Go, the function always + // returns true. + lineWithComment := func(line int) bool { + if f.file == nil { + // Current source file is not Go, so be conservative. + return true + } + for _, group := range f.file.Comments { + startLine := f.fset.Position(group.Pos()).Line + endLine := f.fset.Position(group.End()).Line + if startLine <= line && line <= endLine { + return true + } + } + return false + } // Determine cutpoint where +build comments are no longer valid. // They are valid in leading // comments in the file followed by @@ -46,18 +73,29 @@ func checkBuildTag(name string, data []byte) { if !bytes.HasPrefix(line, slashSlash) { continue } + if !bytes.Contains(line, plusBuild) { + // Check that the comment contains "+build" early, to + // avoid unnecessary lineWithComment calls that may + // incur linear searches. + continue + } + if !lineWithComment(i + 1) { + // This is a line in a Go source file that looks like a + // comment, but actually isn't - such as part of a raw + // string. + continue + } + text := bytes.TrimSpace(line[2:]) if bytes.HasPrefix(text, plusBuild) { fields := bytes.Fields(text) if !bytes.Equal(fields[0], plusBuild) { // Comment is something like +buildasdf not +build. - fmt.Fprintf(os.Stderr, "%s:%d: possible malformed +build comment\n", name, i+1) - setExit(1) + badfLine(f, i+1, "possible malformed +build comment") continue } if i >= cutoff { - fmt.Fprintf(os.Stderr, "%s:%d: +build comment must appear before package clause and be followed by a blank line\n", name, i+1) - setExit(1) + badfLine(f, i+1, "+build comment must appear before package clause and be followed by a blank line") continue } // Check arguments. @@ -65,15 +103,13 @@ func checkBuildTag(name string, data []byte) { for _, arg := range fields[1:] { for _, elem := range strings.Split(string(arg), ",") { if strings.HasPrefix(elem, "!!") { - fmt.Fprintf(os.Stderr, "%s:%d: invalid double negative in build constraint: %s\n", name, i+1, arg) - setExit(1) + badfLine(f, i+1, "invalid double negative in build constraint: %s", arg) break Args } elem = strings.TrimPrefix(elem, "!") for _, c := range elem { if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { - fmt.Fprintf(os.Stderr, "%s:%d: invalid non-alphanumeric build constraint: %s\n", name, i+1, arg) - setExit(1) + badfLine(f, i+1, "invalid non-alphanumeric build constraint: %s", arg) break Args } } @@ -82,9 +118,8 @@ func checkBuildTag(name string, data []byte) { continue } // Comment with +build but not at beginning. - if bytes.Contains(line, plusBuild) && i < cutoff { - fmt.Fprintf(os.Stderr, "%s:%d: possible malformed +build comment\n", name, i+1) - setExit(1) + if i < cutoff { + badfLine(f, i+1, "possible malformed +build comment") continue } } diff --git a/libgo/go/cmd/vet/composite.go b/libgo/go/cmd/vet/composite.go index f704f181bf0..861e040aac4 100644 --- a/libgo/go/cmd/vet/composite.go +++ b/libgo/go/cmd/vet/composite.go @@ -18,7 +18,7 @@ var compositeWhiteList = flag.Bool("compositewhitelist", true, "use composite wh func init() { register("composites", - "check that composite literals used field-keyed elements", + "check that composite literals of types from imported packages use field-keyed elements", checkUnkeyedLiteral, compositeLit) } @@ -38,11 +38,19 @@ func checkUnkeyedLiteral(f *File, node ast.Node) { // skip whitelisted types return } - if _, ok := typ.Underlying().(*types.Struct); !ok { + under := typ.Underlying() + for { + ptr, ok := under.(*types.Pointer) + if !ok { + break + } + under = ptr.Elem().Underlying() + } + if _, ok := under.(*types.Struct); !ok { // skip non-struct composite literals return } - if isLocalType(f, typeName) { + if isLocalType(f, typ) { // allow unkeyed locally defined composite literal return } @@ -63,20 +71,16 @@ func checkUnkeyedLiteral(f *File, node ast.Node) { f.Badf(cl.Pos(), "%s composite literal uses unkeyed fields", typeName) } -func isLocalType(f *File, typeName string) bool { - if strings.HasPrefix(typeName, "struct{") { +func isLocalType(f *File, typ types.Type) bool { + switch x := typ.(type) { + case *types.Struct: // struct literals are local types return true + case *types.Pointer: + return isLocalType(f, x.Elem()) + case *types.Named: + // names in package foo are local to foo_test too + return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(f.pkg.path, "_test") } - - pkgname := f.pkg.path - if strings.HasPrefix(typeName, pkgname+".") { - return true - } - - // treat types as local inside test packages with _test name suffix - if strings.HasSuffix(pkgname, "_test") { - pkgname = pkgname[:len(pkgname)-len("_test")] - } - return strings.HasPrefix(typeName, pkgname+".") + return false } diff --git a/libgo/go/cmd/vet/copylock.go b/libgo/go/cmd/vet/copylock.go index ce14e1af343..ed88ca89603 100644 --- a/libgo/go/cmd/vet/copylock.go +++ b/libgo/go/cmd/vet/copylock.go @@ -234,13 +234,11 @@ func lockPath(tpkg *types.Package, typ types.Type) typePath { return nil } - // We're looking for cases in which a reference to this type - // can be locked, but a value cannot. This differentiates + // We're looking for cases in which a pointer to this type + // is a sync.Locker, but a value is not. This differentiates // embedded interfaces from embedded values. - if plock := types.NewMethodSet(types.NewPointer(typ)).Lookup(tpkg, "Lock"); plock != nil { - if lock := types.NewMethodSet(typ).Lookup(tpkg, "Lock"); lock == nil { - return []types.Type{typ} - } + if types.Implements(types.NewPointer(typ), lockerType) && !types.Implements(typ, lockerType) { + return []types.Type{typ} } nfields := styp.NumFields() @@ -254,3 +252,15 @@ func lockPath(tpkg *types.Package, typ types.Type) typePath { return nil } + +var lockerType *types.Interface + +// Construct a sync.Locker interface type. +func init() { + nullary := types.NewSignature(nil, nil, nil, false) // func() + methods := []*types.Func{ + types.NewFunc(token.NoPos, nil, "Lock", nullary), + types.NewFunc(token.NoPos, nil, "Unlock", nullary), + } + lockerType = types.NewInterface(methods, nil).Complete() +} diff --git a/libgo/go/cmd/vet/dead.go b/libgo/go/cmd/vet/dead.go index 130f619626d..0facec55258 100644 --- a/libgo/go/cmd/vet/dead.go +++ b/libgo/go/cmd/vet/dead.go @@ -45,7 +45,7 @@ func (f *File) updateDead(node ast.Node) { } for _, expr := range cc.List { v := f.pkg.types[expr].Value - if v == nil || constant.BoolVal(v) { + if v == nil || v.Kind() != constant.Bool || constant.BoolVal(v) { continue BodyLoopBool } } diff --git a/libgo/go/cmd/vet/doc.go b/libgo/go/cmd/vet/doc.go index 3df975cacc4..d9af0a88759 100644 --- a/libgo/go/cmd/vet/doc.go +++ b/libgo/go/cmd/vet/doc.go @@ -119,22 +119,17 @@ Printf family Flag: -printf -Suspicious calls to functions in the Printf family, including any functions -with these names, disregarding case: - Print Printf Println - Fprint Fprintf Fprintln - Sprint Sprintf Sprintln - Error Errorf - Fatal Fatalf - Log Logf - Panic Panicf Panicln -The -printfuncs flag can be used to redefine this list. -If the function name ends with an 'f', the function is assumed to take -a format descriptor string in the manner of fmt.Printf. If not, vet -complains about arguments that look like format descriptor strings. +Suspicious calls to fmt.Print, fmt.Printf, and related functions. +The check applies to known functions (for example, those in package fmt) +as well as any detected wrappers of known functions. -It also checks for errors such as using a Writer as the first argument of -Printf. +The -printfuncs flag specifies a comma-separated list of names of +additional known formatting functions. Each name can be of the form +pkg.Name or pkg.Type.Name, where pkg is a complete import path, +or else can be a case-insensitive unqualified identifier like "errorf". +If a listed name ends in f, the function is assumed to be Printf-like, +taking a format string before the argument list. Otherwise it is +assumed to be Print-like, taking a list of arguments with no format string. Range loop variables diff --git a/libgo/go/cmd/vet/main.go b/libgo/go/cmd/vet/main.go index 49c1d32f13d..c50d4885a07 100644 --- a/libgo/go/cmd/vet/main.go +++ b/libgo/go/cmd/vet/main.go @@ -4,10 +4,12 @@ // Vet is a simple checker for static errors in Go source code. // See doc.go for more information. + package main import ( "bytes" + "encoding/gob" "encoding/json" "flag" "fmt" @@ -22,8 +24,11 @@ import ( "io/ioutil" "os" "path/filepath" + "sort" "strconv" "strings" + + "cmd/internal/objabi" ) // Important! If you add flags here, make sure to update cmd/go/internal/vet/vetflag.go. @@ -154,9 +159,31 @@ var ( // checkers is a two-level map. // The outer level is keyed by a nil pointer, one of the AST vars above. // The inner level is keyed by checker name. - checkers = make(map[ast.Node]map[string]func(*File, ast.Node)) + checkers = make(map[ast.Node]map[string]func(*File, ast.Node)) + pkgCheckers = make(map[string]func(*Package)) + exporters = make(map[string]func() interface{}) ) +// The exporters data as written to the vetx output file. +type vetxExport struct { + Name string + Data interface{} +} + +// Vet can provide its own "export information" +// about package A to future invocations of vet +// on packages importing A. If B imports A, +// then running "go vet B" actually invokes vet twice: +// first, it runs vet on A, in "vetx-only" mode, which +// skips most checks and only computes export data +// describing A. Then it runs vet on B, making A's vetx +// data available for consultation. The vet of B +// computes vetx data for B in addition to its +// usual vet checks. + +// register registers the named check function, +// to be called with AST nodes of the given types. +// The registered functions are not called in vetx-only mode. func register(name, usage string, fn func(*File, ast.Node), types ...ast.Node) { report[name] = triStateFlag(name, unset, usage) for _, typ := range types { @@ -169,6 +196,25 @@ func register(name, usage string, fn func(*File, ast.Node), types ...ast.Node) { } } +// registerPkgCheck registers a package-level checking function, +// to be invoked with the whole package being vetted +// before any of the per-node handlers. +// The registered function fn is called even in vetx-only mode +// (see comment above), so fn must take care not to report +// errors when vcfg.VetxOnly is true. +func registerPkgCheck(name string, fn func(*Package)) { + pkgCheckers[name] = fn +} + +// registerExport registers a function to return vetx export data +// that should be saved and provided to future invocations of vet +// when checking packages importing this one. +// The value returned by fn should be nil or else valid to encode using gob. +// Typically a registerExport call is paired with a call to gob.Register. +func registerExport(name string, fn func() interface{}) { + exporters[name] = fn +} + // Usage is a replacement usage function for the flags package. func Usage() { fmt.Fprintf(os.Stderr, "Usage of vet:\n") @@ -195,9 +241,11 @@ type File struct { // Parsed package "foo" when checking package "foo_test" basePkg *Package - // The objects that are receivers of a "String() string" method. + // The keys are the objects that are receivers of a "String() + // string" method. The value reports whether the method has a + // pointer receiver. // This is used by the recursiveStringer method in print.go. - stringers map[*ast.Object]bool + stringerPtrs map[*ast.Object]bool // Registered checkers to run. checkers map[ast.Node][]func(*File, ast.Node) @@ -207,6 +255,7 @@ type File struct { } func main() { + objabi.AddVersionFlag() flag.Usage = Usage flag.Parse() @@ -293,6 +342,9 @@ type vetConfig struct { ImportMap map[string]string PackageFile map[string]string Standard map[string]bool + PackageVetx map[string]string // map from import path to vetx data file + VetxOnly bool // only compute vetx output; don't run ordinary checks + VetxOutput string // file where vetx output should be written SucceedOnTypecheckFailure bool @@ -353,6 +405,28 @@ func doPackageCfg(cfgFile string) { inittypes() mustTypecheck = true doPackage(vcfg.GoFiles, nil) + if vcfg.VetxOutput != "" { + out := make([]vetxExport, 0, len(exporters)) + for name, fn := range exporters { + out = append(out, vetxExport{ + Name: name, + Data: fn(), + }) + } + // Sort the data so that it is consistent across builds. + sort.Slice(out, func(i, j int) bool { + return out[i].Name < out[j].Name + }) + var buf bytes.Buffer + if err := gob.NewEncoder(&buf).Encode(out); err != nil { + errorf("encoding vet output: %v", err) + return + } + if err := ioutil.WriteFile(vcfg.VetxOutput, buf.Bytes(), 0666); err != nil { + errorf("saving vet output: %v", err) + return + } + } } // doPackageDir analyzes the single package found in the directory, if there is one, @@ -413,23 +487,23 @@ func doPackage(names []string, basePkg *Package) *Package { warnf("%s: %s", name, err) return nil } - checkBuildTag(name, data) var parsedFile *ast.File if strings.HasSuffix(name, ".go") { - parsedFile, err = parser.ParseFile(fs, name, data, 0) + parsedFile, err = parser.ParseFile(fs, name, data, parser.ParseComments) if err != nil { warnf("%s: %s", name, err) return nil } astFiles = append(astFiles, parsedFile) } - files = append(files, &File{ + file := &File{ fset: fs, content: data, name: name, file: parsedFile, dead: make(map[ast.Node]bool), - }) + } + files = append(files, file) } if len(astFiles) == 0 { return nil @@ -458,6 +532,19 @@ func doPackage(names []string, basePkg *Package) *Package { } // Check. + for _, file := range files { + file.pkg = pkg + file.basePkg = basePkg + } + for name, fn := range pkgCheckers { + if vet(name) { + fn(pkg) + } + } + if vcfg.VetxOnly { + return pkg + } + chk := make(map[ast.Node][]func(*File, ast.Node)) for typ, set := range checkers { for name, fn := range set { @@ -467,14 +554,12 @@ func doPackage(names []string, basePkg *Package) *Package { } } for _, file := range files { - file.pkg = pkg - file.basePkg = basePkg + checkBuildTag(file) file.checkers = chk if file.file != nil { file.walkFile(file.name, file.file) } } - asmCheck(pkg) return pkg } @@ -627,3 +712,39 @@ func (f *File) gofmt(x ast.Expr) string { printer.Fprint(&f.b, f.fset, x) return f.b.String() } + +// imported[path][key] is previously written export data. +var imported = make(map[string]map[string]interface{}) + +// readVetx reads export data written by a previous +// invocation of vet on an imported package (path). +// The key is the name passed to registerExport +// when the data was originally generated. +// readVetx returns nil if the data is unavailable. +func readVetx(path, key string) interface{} { + if path == "unsafe" || vcfg.ImportPath == "" { + return nil + } + m := imported[path] + if m == nil { + file := vcfg.PackageVetx[path] + if file == "" { + return nil + } + data, err := ioutil.ReadFile(file) + if err != nil { + return nil + } + var out []vetxExport + err = gob.NewDecoder(bytes.NewReader(data)).Decode(&out) + if err != nil { + return nil + } + m = make(map[string]interface{}) + for _, x := range out { + m[x.Name] = x.Data + } + imported[path] = m + } + return m[key] +} diff --git a/libgo/go/cmd/vet/method.go b/libgo/go/cmd/vet/method.go index b13ce2fcb56..5783278d2c2 100644 --- a/libgo/go/cmd/vet/method.go +++ b/libgo/go/cmd/vet/method.go @@ -166,9 +166,7 @@ func (f *File) matchParams(expect []string, actual []ast.Expr, prefix string) bo // Does this one type match? func (f *File) matchParamType(expect string, actual ast.Expr) bool { - if strings.HasPrefix(expect, "=") { - expect = expect[1:] - } + expect = strings.TrimPrefix(expect, "=") // Strip package name if we're in that package. if n := len(f.file.Name.Name); len(expect) > n && expect[:n] == f.file.Name.Name && expect[n] == '.' { expect = expect[n+1:] diff --git a/libgo/go/cmd/vet/print.go b/libgo/go/cmd/vet/print.go index 456fbcc044d..a55da1d3c81 100644 --- a/libgo/go/cmd/vet/print.go +++ b/libgo/go/cmd/vet/print.go @@ -8,6 +8,7 @@ package main import ( "bytes" + "encoding/gob" "flag" "fmt" "go/ast" @@ -15,6 +16,7 @@ import ( "go/token" "go/types" "regexp" + "sort" "strconv" "strings" "unicode/utf8" @@ -27,6 +29,9 @@ func init() { "check printf-like invocations", checkFmtPrintfCall, funcDecl, callExpr) + registerPkgCheck("printf", findPrintfLike) + registerExport("printf", exportPrintfLike) + gob.Register([]printfExport(nil)) } func initPrintFlags() { @@ -44,73 +49,304 @@ func initPrintFlags() { name = name[:colon] } - isPrint[strings.ToLower(name)] = true + if !strings.Contains(name, ".") { + name = strings.ToLower(name) + } + isPrint[name] = true } } -// TODO(rsc): Incorporate user-defined printf wrappers again. -// The general plan is to allow vet of one package P to output -// additional information to supply to later vets of packages -// importing P. Then vet of P can record a list of printf wrappers -// and the later vet using P.Printf will find it in the list and check it. -// That's not ready for Go 1.10. -// When that does happen, uncomment the user-defined printf -// wrapper tests in testdata/print.go. +var localPrintfLike = make(map[string]int) + +type printfExport struct { + Name string + Kind int +} + +// printfImported maps from package name to the printf vet data +// exported by that package. +var printfImported = make(map[string]map[string]int) + +type printfWrapper struct { + name string + fn *ast.FuncDecl + format *ast.Field + args *ast.Field + callers []printfCaller + failed bool // if true, not a printf wrapper +} + +type printfCaller struct { + w *printfWrapper + call *ast.CallExpr +} + +// maybePrintfWrapper decides whether decl (a declared function) may be a wrapper +// around a fmt.Printf or fmt.Print function. If so it returns a printfWrapper +// function describing the declaration. Later processing will analyze the +// graph of potential printf wrappers to pick out the ones that are true wrappers. +// A function may be a Printf or Print wrapper if its last argument is ...interface{}. +// If the next-to-last argument is a string, then this may be a Printf wrapper. +// Otherwise it may be a Print wrapper. +func maybePrintfWrapper(decl ast.Decl) *printfWrapper { + // Look for functions with final argument type ...interface{}. + fn, ok := decl.(*ast.FuncDecl) + if !ok || fn.Body == nil { + return nil + } + name := fn.Name.Name + if fn.Recv != nil { + // For (*T).Name or T.name, use "T.name". + rcvr := fn.Recv.List[0].Type + if ptr, ok := rcvr.(*ast.StarExpr); ok { + rcvr = ptr.X + } + id, ok := rcvr.(*ast.Ident) + if !ok { + return nil + } + name = id.Name + "." + name + } + params := fn.Type.Params.List + if len(params) == 0 { + return nil + } + args := params[len(params)-1] + if len(args.Names) != 1 { + return nil + } + ddd, ok := args.Type.(*ast.Ellipsis) + if !ok { + return nil + } + iface, ok := ddd.Elt.(*ast.InterfaceType) + if !ok || len(iface.Methods.List) > 0 { + return nil + } + var format *ast.Field + if len(params) >= 2 { + p := params[len(params)-2] + if len(p.Names) == 1 { + if id, ok := p.Type.(*ast.Ident); ok && id.Name == "string" { + format = p + } + } + } + + return &printfWrapper{ + name: name, + fn: fn, + format: format, + args: args, + } +} + +// findPrintfLike scans the entire package to find printf-like functions. +func findPrintfLike(pkg *Package) { + if vcfg.ImportPath == "" { // no type or vetx information; don't bother + return + } + + // Gather potential wrappesr and call graph between them. + byName := make(map[string]*printfWrapper) + var wrappers []*printfWrapper + for _, file := range pkg.files { + if file.file == nil { + continue + } + for _, decl := range file.file.Decls { + w := maybePrintfWrapper(decl) + if w == nil { + continue + } + byName[w.name] = w + wrappers = append(wrappers, w) + } + } + + // Walk the graph to figure out which are really printf wrappers. + for _, w := range wrappers { + // Scan function for calls that could be to other printf-like functions. + ast.Inspect(w.fn.Body, func(n ast.Node) bool { + if w.failed { + return false + } + + // TODO: Relax these checks; issue 26555. + if assign, ok := n.(*ast.AssignStmt); ok { + for _, lhs := range assign.Lhs { + if match(lhs, w.format) || match(lhs, w.args) { + // Modifies the format + // string or args in + // some way, so not a + // simple wrapper. + w.failed = true + return false + } + } + } + if un, ok := n.(*ast.UnaryExpr); ok && un.Op == token.AND { + if match(un.X, w.format) || match(un.X, w.args) { + // Taking the address of the + // format string or args, + // so not a simple wrapper. + w.failed = true + return false + } + } + + call, ok := n.(*ast.CallExpr) + if !ok || len(call.Args) == 0 || !match(call.Args[len(call.Args)-1], w.args) { + return true + } + + pkgpath, name, kind := printfNameAndKind(pkg, call.Fun) + if kind != 0 { + checkPrintfFwd(pkg, w, call, kind) + return true + } + + // If the call is to another function in this package, + // maybe we will find out it is printf-like later. + // Remember this call for later checking. + if pkgpath == "" && byName[name] != nil { + callee := byName[name] + callee.callers = append(callee.callers, printfCaller{w, call}) + } + + return true + }) + } +} + +func match(arg ast.Expr, param *ast.Field) bool { + id, ok := arg.(*ast.Ident) + return ok && id.Obj != nil && id.Obj.Decl == param +} + +const ( + kindPrintf = 1 + kindPrint = 2 +) + +// printfLike reports whether a call to fn should be considered a call to a printf-like function. +// It returns 0 (indicating not a printf-like function), kindPrintf, or kindPrint. +func printfLike(pkg *Package, fn ast.Expr, byName map[string]*printfWrapper) int { + if id, ok := fn.(*ast.Ident); ok && id.Obj != nil { + if w := byName[id.Name]; w != nil && id.Obj.Decl == w.fn { + // Found call to function in same package. + return localPrintfLike[id.Name] + } + } + if sel, ok := fn.(*ast.SelectorExpr); ok { + if id, ok := sel.X.(*ast.Ident); ok && id.Name == "fmt" && strings.Contains(sel.Sel.Name, "rint") { + if strings.HasSuffix(sel.Sel.Name, "f") { + return kindPrintf + } + return kindPrint + } + } + return 0 +} + +// checkPrintfFwd checks that a printf-forwarding wrapper is forwarding correctly. +// It diagnoses writing fmt.Printf(format, args) instead of fmt.Printf(format, args...). +func checkPrintfFwd(pkg *Package, w *printfWrapper, call *ast.CallExpr, kind int) { + matched := kind == kindPrint || + kind == kindPrintf && len(call.Args) >= 2 && match(call.Args[len(call.Args)-2], w.format) + if !matched { + return + } + + if !call.Ellipsis.IsValid() { + typ, ok := pkg.types[call.Fun].Type.(*types.Signature) + if !ok { + return + } + if len(call.Args) > typ.Params().Len() { + // If we're passing more arguments than what the + // print/printf function can take, adding an ellipsis + // would break the program. For example: + // + // func foo(arg1 string, arg2 ...interface{} { + // fmt.Printf("%s %v", arg1, arg2) + // } + return + } + if !vcfg.VetxOnly { + desc := "printf" + if kind == kindPrint { + desc = "print" + } + pkg.files[0].Badf(call.Pos(), "missing ... in args forwarded to %s-like function", desc) + } + return + } + name := w.name + if localPrintfLike[name] == 0 { + localPrintfLike[name] = kind + for _, caller := range w.callers { + checkPrintfFwd(pkg, caller.w, caller.call, kind) + } + } +} + +func exportPrintfLike() interface{} { + out := make([]printfExport, 0, len(localPrintfLike)) + for name, kind := range localPrintfLike { + out = append(out, printfExport{ + Name: name, + Kind: kind, + }) + } + sort.Slice(out, func(i, j int) bool { + return out[i].Name < out[j].Name + }) + return out +} // isPrint records the print functions. // If a key ends in 'f' then it is assumed to be a formatted print. var isPrint = map[string]bool{ - "fmt.Errorf": true, - "fmt.Fprint": true, - "fmt.Fprintf": true, - "fmt.Fprintln": true, - "fmt.Print": true, - "fmt.Printf": true, - "fmt.Println": true, - "fmt.Sprint": true, - "fmt.Sprintf": true, - "fmt.Sprintln": true, - "log.Fatal": true, - "log.Fatalf": true, - "log.Fatalln": true, - "log.Logger.Fatal": true, - "log.Logger.Fatalf": true, - "log.Logger.Fatalln": true, - "log.Logger.Panic": true, - "log.Logger.Panicf": true, - "log.Logger.Panicln": true, - "log.Logger.Printf": true, - "log.Logger.Println": true, - "log.Panic": true, - "log.Panicf": true, - "log.Panicln": true, - "log.Print": true, - "log.Printf": true, - "log.Println": true, - "testing.B.Error": true, - "testing.B.Errorf": true, - "testing.B.Fatal": true, - "testing.B.Fatalf": true, - "testing.B.Log": true, - "testing.B.Logf": true, - "testing.B.Skip": true, - "testing.B.Skipf": true, - "testing.T.Error": true, - "testing.T.Errorf": true, - "testing.T.Fatal": true, - "testing.T.Fatalf": true, - "testing.T.Log": true, - "testing.T.Logf": true, - "testing.T.Skip": true, - "testing.T.Skipf": true, - "testing.TB.Error": true, - "testing.TB.Errorf": true, - "testing.TB.Fatal": true, - "testing.TB.Fatalf": true, - "testing.TB.Log": true, - "testing.TB.Logf": true, - "testing.TB.Skip": true, - "testing.TB.Skipf": true, + "fmt.Errorf": true, + "fmt.Fprint": true, + "fmt.Fprintf": true, + "fmt.Fprintln": true, + "fmt.Print": true, + "fmt.Printf": true, + "fmt.Println": true, + "fmt.Sprint": true, + "fmt.Sprintf": true, + "fmt.Sprintln": true, + + // testing.B, testing.T not auto-detected + // because the methods are picked up by embedding. + "testing.B.Error": true, + "testing.B.Errorf": true, + "testing.B.Fatal": true, + "testing.B.Fatalf": true, + "testing.B.Log": true, + "testing.B.Logf": true, + "testing.B.Skip": true, + "testing.B.Skipf": true, + "testing.T.Error": true, + "testing.T.Errorf": true, + "testing.T.Fatal": true, + "testing.T.Fatalf": true, + "testing.T.Log": true, + "testing.T.Logf": true, + "testing.T.Skip": true, + "testing.T.Skipf": true, + + // testing.TB is an interface, so can't detect wrapping. + "testing.TB.Error": true, + "testing.TB.Errorf": true, + "testing.TB.Fatal": true, + "testing.TB.Fatalf": true, + "testing.TB.Log": true, + "testing.TB.Logf": true, + "testing.TB.Skip": true, + "testing.TB.Skipf": true, } // formatString returns the format string argument and its index within @@ -187,12 +423,14 @@ func checkFmtPrintfCall(f *File, node ast.Node) { if d, ok := node.(*ast.FuncDecl); ok && isStringer(f, d) { // Remember we saw this. - if f.stringers == nil { - f.stringers = make(map[*ast.Object]bool) + if f.stringerPtrs == nil { + f.stringerPtrs = make(map[*ast.Object]bool) } if l := d.Recv.List; len(l) == 1 { if n := l[0].Names; len(n) == 1 { - f.stringers[n[0].Obj] = true + typ := f.pkg.types[l[0].Type] + _, ptrRecv := typ.Type.(*types.Pointer) + f.stringerPtrs[n[0].Obj] = ptrRecv } } return @@ -204,66 +442,93 @@ func checkFmtPrintfCall(f *File, node ast.Node) { } // Construct name like pkg.Printf or pkg.Type.Printf for lookup. - var name string - switch x := call.Fun.(type) { + _, name, kind := printfNameAndKind(f.pkg, call.Fun) + if kind == kindPrintf { + f.checkPrintf(call, name) + } + if kind == kindPrint { + f.checkPrint(call, name) + } +} + +func printfName(pkg *Package, called ast.Expr) (pkgpath, name string) { + switch x := called.(type) { case *ast.Ident: - if fn, ok := f.pkg.uses[x].(*types.Func); ok { - var pkg string - if fn.Pkg() == nil || fn.Pkg() == f.pkg.typesPkg { - pkg = vcfg.ImportPath + if fn, ok := pkg.uses[x].(*types.Func); ok { + if fn.Pkg() == nil || fn.Pkg() == pkg.typesPkg { + pkgpath = "" } else { - pkg = fn.Pkg().Path() + pkgpath = fn.Pkg().Path() } - name = pkg + "." + x.Name - break + return pkgpath, x.Name } case *ast.SelectorExpr: // Check for "fmt.Printf". if id, ok := x.X.(*ast.Ident); ok { - if pkgName, ok := f.pkg.uses[id].(*types.PkgName); ok { - name = pkgName.Imported().Path() + "." + x.Sel.Name - break + if pkgName, ok := pkg.uses[id].(*types.PkgName); ok { + return pkgName.Imported().Path(), x.Sel.Name } } // Check for t.Logf where t is a *testing.T. - if sel := f.pkg.selectors[x]; sel != nil { + if sel := pkg.selectors[x]; sel != nil { recv := sel.Recv() if p, ok := recv.(*types.Pointer); ok { recv = p.Elem() } if named, ok := recv.(*types.Named); ok { obj := named.Obj() - var pkg string - if obj.Pkg() == nil || obj.Pkg() == f.pkg.typesPkg { - pkg = vcfg.ImportPath + if obj.Pkg() == nil || obj.Pkg() == pkg.typesPkg { + pkgpath = "" } else { - pkg = obj.Pkg().Path() + pkgpath = obj.Pkg().Path() } - name = pkg + "." + obj.Name() + "." + x.Sel.Name - break + return pkgpath, obj.Name() + "." + x.Sel.Name } } } + return "", "" +} + +func printfNameAndKind(pkg *Package, called ast.Expr) (pkgpath, name string, kind int) { + pkgpath, name = printfName(pkg, called) if name == "" { - return + return pkgpath, name, 0 } - shortName := name[strings.LastIndex(name, ".")+1:] - - _, ok = isPrint[name] - if !ok { - // Next look up just "printf", for use with -printfuncs. - _, ok = isPrint[strings.ToLower(shortName)] + if pkgpath == "" { + kind = localPrintfLike[name] + } else if m, ok := printfImported[pkgpath]; ok { + kind = m[name] + } else { + var m map[string]int + if out, ok := readVetx(pkgpath, "printf").([]printfExport); ok { + m = make(map[string]int) + for _, x := range out { + m[x.Name] = x.Kind + } + } + printfImported[pkgpath] = m + kind = m[name] } - if ok { - if strings.HasSuffix(name, "f") { - f.checkPrintf(call, shortName) - } else { - f.checkPrint(call, shortName) + + if kind == 0 { + _, ok := isPrint[pkgpath+"."+name] + if !ok { + // Next look up just "printf", for use with -printfuncs. + short := name[strings.LastIndex(name, ".")+1:] + _, ok = isPrint[strings.ToLower(short)] + } + if ok { + if strings.HasSuffix(name, "f") { + kind = kindPrintf + } else { + kind = kindPrint + } } } + return pkgpath, name, kind } // isStringer returns true if the provided declaration is a "String() string" @@ -293,6 +558,7 @@ type formatState struct { file *File call *ast.CallExpr argNum int // Which argument we're expecting to format now. + hasIndex bool // Whether the argument is indexed. indexPending bool // Whether we have an indexed argument that has not resolved. nbytes int // number of bytes of the format string consumed. } @@ -317,6 +583,7 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) { // Hard part: check formats against args. argNum := firstArg maxArgNum := firstArg + anyIndex := false for i, w := 0, 0; i < len(format); i += w { w = 1 if format[i] != '%' { @@ -330,6 +597,9 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) { if !f.okPrintfArg(call, state) { // One error per format is enough. return } + if state.hasIndex { + anyIndex = true + } if len(state.argNums) > 0 { // Continue with the next sequential argument. argNum = state.argNums[len(state.argNums)-1] + 1 @@ -344,6 +614,10 @@ func (f *File) checkPrintf(call *ast.CallExpr, name string) { if call.Ellipsis.IsValid() && maxArgNum >= len(call.Args)-1 { return } + // If any formats are indexed, extra arguments are ignored. + if anyIndex { + return + } // There should be no leftover arguments. if maxArgNum != len(call.Args) { expect := maxArgNum - firstArg @@ -402,6 +676,7 @@ func (s *formatState) parseIndex() bool { arg := int(arg32) arg += s.firstArg - 1 // We want to zero-index the actual arguments. s.argNum = arg + s.hasIndex = true s.indexPending = true return true } @@ -522,7 +797,7 @@ var printVerbs = []printVerb{ {'%', noFlag, 0}, {'b', numFlag, argInt | argFloat | argComplex}, {'c', "-", argRune | argInt}, - {'d', numFlag, argInt}, + {'d', numFlag, argInt | argPointer}, {'e', sharpNumFlag, argFloat | argComplex}, {'E', sharpNumFlag, argFloat | argComplex}, {'f', sharpNumFlag, argFloat | argComplex}, @@ -537,8 +812,8 @@ var printVerbs = []printVerb{ {'T', "-", anyType}, {'U', "-#", argRune | argInt}, {'v', allFlags, anyType}, - {'x', sharpNumFlag, argRune | argInt | argString}, - {'X', sharpNumFlag, argRune | argInt | argString}, + {'x', sharpNumFlag, argRune | argInt | argString | argPointer}, + {'X', sharpNumFlag, argRune | argInt | argString | argPointer}, } // okPrintfArg compares the formatState to the arguments actually present, @@ -569,6 +844,11 @@ func (f *File) okPrintfArg(call *ast.CallExpr, state *formatState) (ok bool) { return false } for _, flag := range state.flags { + // TODO: Disable complaint about '0' for Go 1.10. To be fixed properly in 1.11. + // See issues 23598 and 23605. + if flag == '0' { + continue + } if !strings.ContainsRune(v.flags, rune(flag)) { f.Badf(call.Pos(), "%s format %s has unrecognized flag %c", state.name, state.format, flag) return false @@ -623,9 +903,10 @@ func (f *File) okPrintfArg(call *ast.CallExpr, state *formatState) (ok bool) { // recursiveStringer reports whether the provided argument is r or &r for the // fmt.Stringer receiver identifier r. func (f *File) recursiveStringer(e ast.Expr) bool { - if len(f.stringers) == 0 { + if len(f.stringerPtrs) == 0 { return false } + ptr := false var obj *ast.Object switch e := e.(type) { case *ast.Ident: @@ -633,13 +914,13 @@ func (f *File) recursiveStringer(e ast.Expr) bool { case *ast.UnaryExpr: if id, ok := e.X.(*ast.Ident); ok && e.Op == token.AND { obj = id.Obj + ptr = true } } // It's unlikely to be a recursive stringer if it has a Format method. if typ := f.pkg.types[e].Type; typ != nil { - // Not a perfect match; see issue 6259. - if f.hasMethod(typ, "Format") { + if f.isFormatter(typ) { return false } } @@ -647,7 +928,16 @@ func (f *File) recursiveStringer(e ast.Expr) bool { // We compare the underlying Object, which checks that the identifier // is the one we declared as the receiver for the String method in // which this printf appears. - return f.stringers[obj] + ptrRecv, exist := f.stringerPtrs[obj] + if !exist { + return false + } + // We also need to check that using &t when we declared String + // on (t *T) is ok; in such a case, the address is printed. + if ptr && ptrRecv { + return false + } + return true } // isFunctionValue reports whether the expression is a function as opposed to a function call. @@ -681,7 +971,7 @@ func (f *File) argCanBeChecked(call *ast.CallExpr, formatArg int, state *formatS // There are bad indexes in the format or there are fewer arguments than the format needs. // This is the argument number relative to the format: Printf("%s", "hi") will give 1 for the "hi". arg := argNum - state.firstArg + 1 // People think of arguments as 1-indexed. - f.Badf(call.Pos(), "%s format %s reads arg #%d, but call has only %v", state.name, state.format, arg, count(len(call.Args)-state.firstArg, "arg")) + f.Badf(call.Pos(), "%s format %s reads arg #%d, but call has %v", state.name, state.format, arg, count(len(call.Args)-state.firstArg, "arg")) return false } @@ -694,7 +984,7 @@ const ( flagsRE = `[+\-#]*` indexOptRE = `(\[[0-9]+\])?` numOptRE = `([0-9]+|` + indexOptRE + `\*)?` - verbRE = `[bcdefgopqstvxEFGUX]` + verbRE = `[bcdefgopqstvxEFGTUX]` ) // checkPrint checks a call to an unformatted print routine such as Println. diff --git a/libgo/go/cmd/vet/testdata/asm/asm.go b/libgo/go/cmd/vet/testdata/asm/asm.go index e6d6d031061..2237ddc3b05 100644 --- a/libgo/go/cmd/vet/testdata/asm/asm.go +++ b/libgo/go/cmd/vet/testdata/asm/asm.go @@ -43,3 +43,6 @@ func wrapper(x int) func f15271() (x uint32) func f17584(x float32, y complex64) + +func noframe1(x int32) +func noframe2(x int32) diff --git a/libgo/go/cmd/vet/testdata/asm/asm3.s b/libgo/go/cmd/vet/testdata/asm/asm3.s index 3d69356a0f9..83e53862d7d 100644 --- a/libgo/go/cmd/vet/testdata/asm/asm3.s +++ b/libgo/go/cmd/vet/testdata/asm/asm3.s @@ -176,3 +176,17 @@ TEXT ·leaf(SB),0,$-4-12 MOVW y+4(FP), AX MOVW AX, ret+8(FP) RET + +TEXT ·noframe1(SB),0,$0-4 + MOVW 0(R13), AX // Okay; our saved LR + MOVW 4(R13), AX // Okay; caller's saved LR + MOVW x+8(R13), AX // Okay; x argument + MOVW 12(R13), AX // ERROR "use of 12\(R13\) points beyond argument frame" + RET + +TEXT ·noframe2(SB),NOFRAME,$0-4 + MOVW 0(R13), AX // Okay; caller's saved LR + MOVW x+4(R13), AX // Okay; x argument + MOVW 8(R13), AX // ERROR "use of 8\(R13\) points beyond argument frame" + MOVW 12(R13), AX // ERROR "use of 12\(R13\) points beyond argument frame" + RET diff --git a/libgo/go/cmd/vet/testdata/atomic.go b/libgo/go/cmd/vet/testdata/atomic.go index d5a8e611844..69730b4e6f0 100644 --- a/libgo/go/cmd/vet/testdata/atomic.go +++ b/libgo/go/cmd/vet/testdata/atomic.go @@ -43,10 +43,20 @@ func AtomicTests() { { // A variable declaration creates a new variable in the current scope. - x := atomic.AddUint64(&x, 1) // ERROR "declaration of .x. shadows declaration at testdata/atomic.go:16" + x := atomic.AddUint64(&x, 1) // ERROR "declaration of .x. shadows declaration at atomic.go:16" // Re-declaration assigns a new value. x, w := atomic.AddUint64(&x, 1), 10 // ERROR "direct assignment to atomic value" _ = w } } + +type T struct{} + +func (T) AddUint64(addr *uint64, delta uint64) uint64 { return 0 } + +func NonAtomic() { + x := uint64(1) + var atomic T + x = atomic.AddUint64(&x, 1) // ok; not the imported pkg +} diff --git a/libgo/go/cmd/vet/testdata/bool.go b/libgo/go/cmd/vet/testdata/bool.go index af6cc011dd6..80c44d25ca3 100644 --- a/libgo/go/cmd/vet/testdata/bool.go +++ b/libgo/go/cmd/vet/testdata/bool.go @@ -8,15 +8,33 @@ package testdata import "io" +type T int + +func (t T) Foo() int { return int(t) } + +type FT func() int + +var S []int + func RatherStupidConditions() { var f, g func() int if f() == 0 || f() == 0 { // OK f might have side effects } + var t T + _ = t.Foo() == 2 || t.Foo() == 2 // OK Foo might have side effects if v, w := f(), g(); v == w || v == w { // ERROR "redundant or: v == w || v == w" } _ = f == nil || f == nil // ERROR "redundant or: f == nil || f == nil" - _ = i == byte(1) || i == byte(1) // TODO conversions are treated as if they may have side effects + _ = i == byte(1) || i == byte(1) // ERROR "redundant or: i == byte(1) || i == byte(1)" + _ = i == T(2) || i == T(2) // ERROR "redundant or: i == T(2) || i == T(2)" + _ = FT(f) == nil || FT(f) == nil // ERROR "redundant or: FT(f) == nil || FT(f) == nil" + + _ = (func() int)(f) == nil || (func() int)(f) == nil // ERROR "redundant or: (func() int)(f) == nil || (func() int)(f) == nil" + _ = append(S, 3) == nil || append(S, 3) == nil // OK append has side effects + + var namedFuncVar FT + _ = namedFuncVar() == namedFuncVar() // OK still func calls var c chan int _ = 0 == <-c || 0 == <-c // OK subsequent receives may yield different values diff --git a/libgo/go/cmd/vet/testdata/buildtag/buildtag.go b/libgo/go/cmd/vet/testdata/buildtag/buildtag.go index f12f895dfb1..c2fd6aaaf2f 100644 --- a/libgo/go/cmd/vet/testdata/buildtag/buildtag.go +++ b/libgo/go/cmd/vet/testdata/buildtag/buildtag.go @@ -9,6 +9,10 @@ package testdata -// +build toolate // ERROR "build comment must appear before package clause and be followed by a blank line" +// +build toolate // ERROR "build comment must appear before package clause and be followed by a blank line$" var _ = 3 + +var _ = ` +// +build notacomment +` diff --git a/libgo/go/cmd/vet/testdata/composite.go b/libgo/go/cmd/vet/testdata/composite.go index 2e6ce262cc1..3fe3eac78cb 100644 --- a/libgo/go/cmd/vet/testdata/composite.go +++ b/libgo/go/cmd/vet/testdata/composite.go @@ -62,6 +62,11 @@ var Okay6 = []MyStruct{ {"aa", "bb", "cc"}, } +var Okay7 = []*MyStruct{ + {"foo", "bar", "baz"}, + {"aa", "bb", "cc"}, +} + // Testing is awkward because we need to reference things from a separate package // to trigger the warnings. @@ -101,3 +106,15 @@ var whitelistedPoint = image.Point{1, 2} // Do not check type from unknown package. // See issue 15408. var unknownPkgVar = unknownpkg.Foobar{"foo", "bar"} + +// A named pointer slice of CaseRange to test issue 23539. In +// particular, we're interested in how some slice elements omit their +// type. +var goodNamedPointerSliceLiteral = []*unicode.CaseRange{ + {Lo: 1, Hi: 2}, + &unicode.CaseRange{Lo: 1, Hi: 2}, +} +var badNamedPointerSliceLiteral = []*unicode.CaseRange{ + {1, 2}, // ERROR "unkeyed fields" + &unicode.CaseRange{1, 2}, // ERROR "unkeyed fields" +} diff --git a/libgo/go/cmd/vet/testdata/deadcode.go b/libgo/go/cmd/vet/testdata/deadcode.go index 5370bc32f65..d1a7adee38d 100644 --- a/libgo/go/cmd/vet/testdata/deadcode.go +++ b/libgo/go/cmd/vet/testdata/deadcode.go @@ -2123,3 +2123,12 @@ var _ = func() { // goto without label used to panic goto } + +func _() int { + // Empty switch tag with non-bool case value used to panic. + switch { + case 1: + println() + } + println() +} diff --git a/libgo/go/cmd/vet/testdata/print.go b/libgo/go/cmd/vet/testdata/print.go index 55ab84fae76..ecafed5fa2f 100644 --- a/libgo/go/cmd/vet/testdata/print.go +++ b/libgo/go/cmd/vet/testdata/print.go @@ -14,6 +14,7 @@ package testdata import ( "fmt" . "fmt" + logpkg "log" // renamed to make it harder to see "math" "os" "testing" @@ -79,7 +80,7 @@ func PrintfTests() { fmt.Printf("%G %G %G %G", 3e9, x, fslice, c) fmt.Printf("%b %b %b %b", 3e9, x, fslice, c) fmt.Printf("%o %o", 3, i) - fmt.Printf("%p %p", p, nil) + fmt.Printf("%p", p) fmt.Printf("%q %q %q %q", 3, i, 'x', r) fmt.Printf("%s %s %s", "hi", s, []byte{65}) fmt.Printf("%t %t", true, b) @@ -122,6 +123,7 @@ func PrintfTests() { fmt.Printf("%g", imap) // ERROR "Printf format %g has arg imap of wrong type map\[int\]int" fmt.Printf("%G", i) // ERROR "Printf format %G has arg i of wrong type int" fmt.Printf("%o", x) // ERROR "Printf format %o has arg x of wrong type float64" + fmt.Printf("%p", nil) // ERROR "Printf format %p has arg nil of wrong type untyped nil" fmt.Printf("%p", 23) // ERROR "Printf format %p has arg 23 of wrong type int" fmt.Printf("%q", x) // ERROR "Printf format %q has arg x of wrong type float64" fmt.Printf("%s", b) // ERROR "Printf format %s has arg b of wrong type bool" @@ -130,8 +132,8 @@ func PrintfTests() { fmt.Printf("%U", x) // ERROR "Printf format %U has arg x of wrong type float64" fmt.Printf("%x", nil) // ERROR "Printf format %x has arg nil of wrong type untyped nil" fmt.Printf("%X", 2.3) // ERROR "Printf format %X has arg 2.3 of wrong type float64" - fmt.Printf("%s", stringerv) // ERROR "Printf format %s has arg stringerv of wrong type testdata.stringer" - fmt.Printf("%t", stringerv) // ERROR "Printf format %t has arg stringerv of wrong type testdata.stringer" + fmt.Printf("%s", stringerv) // ERROR "Printf format %s has arg stringerv of wrong type testdata.ptrStringer" + fmt.Printf("%t", stringerv) // ERROR "Printf format %t has arg stringerv of wrong type testdata.ptrStringer" fmt.Printf("%s", embeddedStringerv) // ERROR "Printf format %s has arg embeddedStringerv of wrong type testdata.embeddedStringer" fmt.Printf("%t", embeddedStringerv) // ERROR "Printf format %t has arg embeddedStringerv of wrong type testdata.embeddedStringer" fmt.Printf("%q", notstringerv) // ERROR "Printf format %q has arg notstringerv of wrong type testdata.notstringer" @@ -147,6 +149,7 @@ func PrintfTests() { fmt.Println() // not an error fmt.Println("%s", "hi") // ERROR "Println call has possible formatting directive %s" fmt.Println("%v", "hi") // ERROR "Println call has possible formatting directive %v" + fmt.Println("%T", "hi") // ERROR "Println call has possible formatting directive %T" fmt.Println("0.0%") // correct (trailing % couldn't be a formatting directive) fmt.Printf("%s", "hi", 3) // ERROR "Printf call needs 1 arg but has 2 args" _ = fmt.Sprintf("%"+("s"), "hi", 3) // ERROR "Sprintf call needs 1 arg but has 2 args" @@ -166,13 +169,25 @@ func PrintfTests() { Printf("hi") // ok const format = "%s %s\n" Printf(format, "hi", "there") - Printf(format, "hi") // ERROR "Printf format %s reads arg #2, but call has only 1 arg$" - Printf("%s %d %.3v %q", "str", 4) // ERROR "Printf format %.3v reads arg #3, but call has only 2 args" - f := new(stringer) + Printf(format, "hi") // ERROR "Printf format %s reads arg #2, but call has 1 arg$" + Printf("%s %d %.3v %q", "str", 4) // ERROR "Printf format %.3v reads arg #3, but call has 2 args" + f := new(ptrStringer) f.Warn(0, "%s", "hello", 3) // ERROR "Warn call has possible formatting directive %s" f.Warnf(0, "%s", "hello", 3) // ERROR "Warnf call needs 1 arg but has 2 args" f.Warnf(0, "%r", "hello") // ERROR "Warnf format %r has unknown verb r" f.Warnf(0, "%#s", "hello") // ERROR "Warnf format %#s has unrecognized flag #" + f.Warn2(0, "%s", "hello", 3) // ERROR "Warn2 call has possible formatting directive %s" + f.Warnf2(0, "%s", "hello", 3) // ERROR "Warnf2 call needs 1 arg but has 2 args" + f.Warnf2(0, "%r", "hello") // ERROR "Warnf2 format %r has unknown verb r" + f.Warnf2(0, "%#s", "hello") // ERROR "Warnf2 format %#s has unrecognized flag #" + f.Wrap(0, "%s", "hello", 3) // ERROR "Wrap call has possible formatting directive %s" + f.Wrapf(0, "%s", "hello", 3) // ERROR "Wrapf call needs 1 arg but has 2 args" + f.Wrapf(0, "%r", "hello") // ERROR "Wrapf format %r has unknown verb r" + f.Wrapf(0, "%#s", "hello") // ERROR "Wrapf format %#s has unrecognized flag #" + f.Wrap2(0, "%s", "hello", 3) // ERROR "Wrap2 call has possible formatting directive %s" + f.Wrapf2(0, "%s", "hello", 3) // ERROR "Wrapf2 call needs 1 arg but has 2 args" + f.Wrapf2(0, "%r", "hello") // ERROR "Wrapf2 format %r has unknown verb r" + f.Wrapf2(0, "%#s", "hello") // ERROR "Wrapf2 format %#s has unrecognized flag #" fmt.Printf("%#s", FormatterVal(true)) // correct (the type is responsible for formatting) Printf("d%", 2) // ERROR "Printf format % is missing verb at end of string" Printf("%d", percentDV) @@ -180,6 +195,7 @@ func PrintfTests() { Printf("%d", notPercentDV) // ERROR "Printf format %d has arg notPercentDV of wrong type testdata.notPercentDStruct" Printf("%d", ¬PercentDV) // ERROR "Printf format %d has arg ¬PercentDV of wrong type \*testdata.notPercentDStruct" Printf("%p", ¬PercentDV) // Works regardless: we print it as a pointer. + Printf("%q", &percentDV) // ERROR "Printf format %q has arg &percentDV of wrong type \*testdata.percentDStruct" Printf("%s", percentSV) Printf("%s", &percentSV) // Good argument reorderings. @@ -240,7 +256,7 @@ func PrintfTests() { // Multiple string arguments before variadic args // errorf("WARNING", "foobar") // OK // errorf("INFO", "s=%s, n=%d", "foo", 1) // OK - // errorf("ERROR", "%d") // no error "errorf format %d reads arg #1, but call has only 0 args" + // errorf("ERROR", "%d") // no error "errorf format %d reads arg #1, but call has 0 args" // Printf from external package // externalprintf.Printf("%d", 42) // OK @@ -248,7 +264,7 @@ func PrintfTests() { // level := 123 // externalprintf.Logf(level, "%d", 42) // OK // externalprintf.Errorf(level, level, "foo %q bar", "foobar") // OK - // externalprintf.Logf(level, "%d") // no error "Logf format %d reads arg #1, but call has only 0 args" + // externalprintf.Logf(level, "%d") // no error "Logf format %d reads arg #1, but call has 0 args" // var formatStr = "%s %s" // externalprintf.Sprintf(formatStr, "a", "b") // OK // externalprintf.Logf(level, formatStr, "a", "b") // OK @@ -269,9 +285,10 @@ func PrintfTests() { Printf("%d %[0]d %d %[2]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[0\]" Printf("%d %[3]d %d %[-2]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[-2\]" Printf("%d %[3]d %d %[2234234234234]d x", 1, 2, 3, 4) // ERROR "Printf format has invalid argument index \[2234234234234\]" - Printf("%d %[3]d %-10d %[2]d x", 1, 2, 3) // ERROR "Printf format %-10d reads arg #4, but call has only 3 args" - Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4, 5) // ERROR "Printf call needs 4 args but has 5 args" + Printf("%d %[3]d %-10d %[2]d x", 1, 2, 3) // ERROR "Printf format %-10d reads arg #4, but call has 3 args" Printf("%[1][3]d x", 1, 2) // ERROR "Printf format %\[1\]\[ has unknown verb \[" + Printf("%[1]d x", 1, 2) // OK + Printf("%d %[3]d %d %[2]d x", 1, 2, 3, 4, 5) // OK // wrote Println but meant Fprintln Printf("%p\n", os.Stdout) // OK @@ -279,6 +296,31 @@ func PrintfTests() { Printf(someString(), "hello") // OK + // Printf wrappers in package log should be detected automatically + logpkg.Fatal("%d", 1) // ERROR "Fatal call has possible formatting directive %d" + logpkg.Fatalf("%d", "x") // ERROR "Fatalf format %d has arg \x22x\x22 of wrong type string" + logpkg.Fatalln("%d", 1) // ERROR "Fatalln call has possible formatting directive %d" + logpkg.Panic("%d", 1) // ERROR "Panic call has possible formatting directive %d" + logpkg.Panicf("%d", "x") // ERROR "Panicf format %d has arg \x22x\x22 of wrong type string" + logpkg.Panicln("%d", 1) // ERROR "Panicln call has possible formatting directive %d" + logpkg.Print("%d", 1) // ERROR "Print call has possible formatting directive %d" + logpkg.Printf("%d", "x") // ERROR "Printf format %d has arg \x22x\x22 of wrong type string" + logpkg.Println("%d", 1) // ERROR "Println call has possible formatting directive %d" + + // Methods too. + var l *logpkg.Logger + l.Fatal("%d", 1) // ERROR "Fatal call has possible formatting directive %d" + l.Fatalf("%d", "x") // ERROR "Fatalf format %d has arg \x22x\x22 of wrong type string" + l.Fatalln("%d", 1) // ERROR "Fatalln call has possible formatting directive %d" + l.Panic("%d", 1) // ERROR "Panic call has possible formatting directive %d" + l.Panicf("%d", "x") // ERROR "Panicf format %d has arg \x22x\x22 of wrong type string" + l.Panicln("%d", 1) // ERROR "Panicln call has possible formatting directive %d" + l.Print("%d", 1) // ERROR "Print call has possible formatting directive %d" + l.Printf("%d", "x") // ERROR "Printf format %d has arg \x22x\x22 of wrong type string" + l.Println("%d", 1) // ERROR "Println call has possible formatting directive %d" + + // Issue 26486 + dbg("", 1) // no error "call has arguments but no formatting directive" } func someString() string { return "X" } @@ -352,25 +394,65 @@ func multi() []interface{} { panic("don't call - testing only") } -type stringer float64 +type stringer int -var stringerv stringer +func (stringer) String() string { return "string" } -func (*stringer) String() string { +type ptrStringer float64 + +var stringerv ptrStringer + +func (*ptrStringer) String() string { return "string" } -func (*stringer) Warn(int, ...interface{}) string { +func (p *ptrStringer) Warn2(x int, args ...interface{}) string { + return p.Warn(x, args...) +} + +func (p *ptrStringer) Warnf2(x int, format string, args ...interface{}) string { + return p.Warnf(x, format, args...) +} + +func (*ptrStringer) Warn(x int, args ...interface{}) string { return "warn" } -func (*stringer) Warnf(int, string, ...interface{}) string { +func (*ptrStringer) Warnf(x int, format string, args ...interface{}) string { return "warnf" } +func (p *ptrStringer) Wrap2(x int, args ...interface{}) string { + return p.Wrap(x, args...) +} + +func (p *ptrStringer) Wrapf2(x int, format string, args ...interface{}) string { + return p.Wrapf(x, format, args...) +} + +func (*ptrStringer) Wrap(x int, args ...interface{}) string { + return fmt.Sprint(args...) +} + +func (*ptrStringer) Wrapf(x int, format string, args ...interface{}) string { + return fmt.Sprintf(format, args...) +} + +func (*ptrStringer) BadWrap(x int, args ...interface{}) string { + return fmt.Sprint(args) // ERROR "missing ... in args forwarded to print-like function" +} + +func (*ptrStringer) BadWrapf(x int, format string, args ...interface{}) string { + return fmt.Sprintf(format, args) // ERROR "missing ... in args forwarded to printf-like function" +} + +func (*ptrStringer) WrapfFalsePositive(x int, arg1 string, arg2 ...interface{}) string { + return fmt.Sprintf("%s %v", arg1, arg2) +} + type embeddedStringer struct { foo string - stringer + ptrStringer bar int } @@ -440,6 +522,7 @@ type recursivePtrStringer int func (p *recursivePtrStringer) String() string { _ = fmt.Sprintf("%v", *p) + _ = fmt.Sprint(&p) // ok; prints address return fmt.Sprintln(p) // ERROR "Sprintln arg p causes recursive call to String method" } @@ -478,13 +561,17 @@ type RecursiveStruct2 struct { var recursiveStruct1V = &RecursiveStruct1{} -// Issue 17798: unexported stringer cannot be formatted. +type unexportedInterface struct { + f interface{} +} + +// Issue 17798: unexported ptrStringer cannot be formatted. type unexportedStringer struct { - t stringer + t ptrStringer } type unexportedStringerOtherFields struct { s string - t stringer + t ptrStringer S string } @@ -502,7 +589,23 @@ type errorer struct{} func (e errorer) Error() string { return "errorer" } +type unexportedCustomError struct { + e errorer +} + +type errorInterface interface { + error + ExtraMethod() +} + +type unexportedErrorInterface struct { + e errorInterface +} + func UnexportedStringerOrError() { + fmt.Printf("%s", unexportedInterface{"foo"}) // ok; prints {foo} + fmt.Printf("%s", unexportedInterface{3}) // ok; we can't see the problem + us := unexportedStringer{} fmt.Printf("%s", us) // ERROR "Printf format %s has arg us of wrong type testdata.unexportedStringer" fmt.Printf("%s", &us) // ERROR "Printf format %s has arg &us of wrong type [*]testdata.unexportedStringer" @@ -528,8 +631,37 @@ func UnexportedStringerOrError() { fmt.Printf("%s", uef) // ERROR "Printf format %s has arg uef of wrong type testdata.unexportedErrorOtherFields" fmt.Printf("%s", &uef) // ERROR "Printf format %s has arg &uef of wrong type [*]testdata.unexportedErrorOtherFields" + uce := unexportedCustomError{ + e: errorer{}, + } + fmt.Printf("%s", uce) // ERROR "Printf format %s has arg uce of wrong type testdata.unexportedCustomError" + + uei := unexportedErrorInterface{} + fmt.Printf("%s", uei) // ERROR "Printf format %s has arg uei of wrong type testdata.unexportedErrorInterface" fmt.Println("foo\n", "bar") // not an error - fmt.Println("foo\n") // ERROR "Println arg list ends with redundant newline" - fmt.Println("foo\\n") // not an error - fmt.Println(`foo\n`) // not an error + + fmt.Println("foo\n") // ERROR "Println arg list ends with redundant newline" + fmt.Println("foo\\n") // not an error + fmt.Println(`foo\n`) // not an error + + intSlice := []int{3, 4} + fmt.Printf("%s", intSlice) // ERROR "Printf format %s has arg intSlice of wrong type \[\]int" + nonStringerArray := [1]unexportedStringer{{}} + fmt.Printf("%s", nonStringerArray) // ERROR "Printf format %s has arg nonStringerArray of wrong type \[1\]testdata.unexportedStringer" + fmt.Printf("%s", []stringer{3, 4}) // not an error + fmt.Printf("%s", [2]stringer{3, 4}) // not an error +} + +// TODO: Disable complaint about '0' for Go 1.10. To be fixed properly in 1.11. +// See issues 23598 and 23605. +func DisableErrorForFlag0() { + fmt.Printf("%0t", true) +} + +// Issue 26486. +func dbg(format string, args ...interface{}) { + if format == "" { + format = "%v" + } + fmt.Printf(format, args...) } diff --git a/libgo/go/cmd/vet/testdata/shadow.go b/libgo/go/cmd/vet/testdata/shadow.go index 3b61137b87c..c55cb2772a9 100644 --- a/libgo/go/cmd/vet/testdata/shadow.go +++ b/libgo/go/cmd/vet/testdata/shadow.go @@ -17,7 +17,7 @@ func ShadowRead(f *os.File, buf []byte) (err error) { _ = err } if f != nil { - _, err := f.Read(buf) // ERROR "declaration of .err. shadows declaration at testdata/shadow.go:13" + _, err := f.Read(buf) // ERROR "declaration of .err. shadows declaration at shadow.go:13" if err != nil { return err } @@ -25,8 +25,8 @@ func ShadowRead(f *os.File, buf []byte) (err error) { _ = i } if f != nil { - x := one() // ERROR "declaration of .x. shadows declaration at testdata/shadow.go:14" - var _, err = f.Read(buf) // ERROR "declaration of .err. shadows declaration at testdata/shadow.go:13" + x := one() // ERROR "declaration of .x. shadows declaration at shadow.go:14" + var _, err = f.Read(buf) // ERROR "declaration of .err. shadows declaration at shadow.go:13" if x == 1 && err != nil { return err } @@ -46,7 +46,7 @@ func ShadowRead(f *os.File, buf []byte) (err error) { if shadowTemp := shadowTemp; true { // OK: obviously intentional idiomatic redeclaration var f *os.File // OK because f is not mentioned later in the function. // The declaration of x is a shadow because x is mentioned below. - var x int // ERROR "declaration of .x. shadows declaration at testdata/shadow.go:14" + var x int // ERROR "declaration of .x. shadows declaration at shadow.go:14" _, _, _ = x, f, shadowTemp } // Use a couple of variables to trigger shadowing errors. diff --git a/libgo/go/cmd/vet/testdata/structtag.go b/libgo/go/cmd/vet/testdata/structtag.go index c87e42f5d00..ce21e803c80 100644 --- a/libgo/go/cmd/vet/testdata/structtag.go +++ b/libgo/go/cmd/vet/testdata/structtag.go @@ -44,40 +44,40 @@ type AnonymousXML struct{} type DuplicateJSONFields struct { JSON int `json:"a"` - DuplicateJSON int `json:"a"` // ERROR "struct field DuplicateJSON repeats json tag .a. also at testdata/structtag.go:46" + DuplicateJSON int `json:"a"` // ERROR "struct field DuplicateJSON repeats json tag .a. also at structtag.go:46" IgnoredJSON int `json:"-"` OtherIgnoredJSON int `json:"-"` OmitJSON int `json:",omitempty"` OtherOmitJSON int `json:",omitempty"` - DuplicateOmitJSON int `json:"a,omitempty"` // ERROR "struct field DuplicateOmitJSON repeats json tag .a. also at testdata/structtag.go:46" + DuplicateOmitJSON int `json:"a,omitempty"` // ERROR "struct field DuplicateOmitJSON repeats json tag .a. also at structtag.go:46" NonJSON int `foo:"a"` DuplicateNonJSON int `foo:"a"` Embedded struct { DuplicateJSON int `json:"a"` // OK because its not in the same struct type } - AnonymousJSON `json:"a"` // ERROR "struct field AnonymousJSON repeats json tag .a. also at testdata/structtag.go:46" + AnonymousJSON `json:"a"` // ERROR "struct field AnonymousJSON repeats json tag .a. also at structtag.go:46" XML int `xml:"a"` - DuplicateXML int `xml:"a"` // ERROR "struct field DuplicateXML repeats xml tag .a. also at testdata/structtag.go:60" + DuplicateXML int `xml:"a"` // ERROR "struct field DuplicateXML repeats xml tag .a. also at structtag.go:60" IgnoredXML int `xml:"-"` OtherIgnoredXML int `xml:"-"` OmitXML int `xml:",omitempty"` OtherOmitXML int `xml:",omitempty"` - DuplicateOmitXML int `xml:"a,omitempty"` // ERROR "struct field DuplicateOmitXML repeats xml tag .a. also at testdata/structtag.go:60" + DuplicateOmitXML int `xml:"a,omitempty"` // ERROR "struct field DuplicateOmitXML repeats xml tag .a. also at structtag.go:60" NonXML int `foo:"a"` DuplicateNonXML int `foo:"a"` Embedded struct { DuplicateXML int `xml:"a"` // OK because its not in the same struct type } - AnonymousXML `xml:"a"` // ERROR "struct field AnonymousXML repeats xml tag .a. also at testdata/structtag.go:60" + AnonymousXML `xml:"a"` // ERROR "struct field AnonymousXML repeats xml tag .a. also at structtag.go:60" Attribute struct { XMLName xml.Name `xml:"b"` NoDup int `xml:"b"` // OK because XMLName above affects enclosing struct. Attr int `xml:"b,attr"` // OK because 0 is valid. - DupAttr int `xml:"b,attr"` // ERROR "struct field DupAttr repeats xml attribute tag .b. also at testdata/structtag.go:76" - DupOmitAttr int `xml:"b,omitempty,attr"` // ERROR "struct field DupOmitAttr repeats xml attribute tag .b. also at testdata/structtag.go:76" + DupAttr int `xml:"b,attr"` // ERROR "struct field DupAttr repeats xml attribute tag .b. also at structtag.go:76" + DupOmitAttr int `xml:"b,omitempty,attr"` // ERROR "struct field DupOmitAttr repeats xml attribute tag .b. also at structtag.go:76" - AnonymousXML `xml:"b,attr"` // ERROR "struct field AnonymousXML repeats xml attribute tag .b. also at testdata/structtag.go:76" + AnonymousXML `xml:"b,attr"` // ERROR "struct field AnonymousXML repeats xml attribute tag .b. also at structtag.go:76" } } diff --git a/libgo/go/cmd/vet/types.go b/libgo/go/cmd/vet/types.go index d83611b4da0..5f8e481e01b 100644 --- a/libgo/go/cmd/vet/types.go +++ b/libgo/go/cmd/vet/types.go @@ -12,7 +12,6 @@ import ( "go/importer" "go/token" "go/types" - "runtime" ) // stdImporter is the importer we use to import packages. @@ -173,7 +172,7 @@ func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Exp return true // %s matches []byte } // Recur: []int matches %d. - return t&argPointer != 0 || f.matchArgTypeInternal(t, typ.Elem().Underlying(), arg, inProgress) + return t&argPointer != 0 || f.matchArgTypeInternal(t, typ.Elem(), arg, inProgress) case *types.Slice: // Same as array. @@ -202,8 +201,8 @@ func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Exp if str, ok := typ.Elem().Underlying().(*types.Struct); ok { return f.matchStructArgType(t, str, arg, inProgress) } - // The rest can print with %p as pointers, or as integers with %x etc. - return t&(argInt|argPointer) != 0 + // Check whether the rest can print pointers. + return t&argPointer != 0 case *types.Struct: return f.matchStructArgType(t, typ, arg, inProgress) @@ -255,7 +254,7 @@ func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Exp return t&(argInt|argRune) != 0 case types.UntypedNil: - return t&argPointer != 0 // TODO? + return false case types.Invalid: if *verbose { @@ -270,7 +269,19 @@ func (f *File) matchArgTypeInternal(t printfArgType, typ types.Type, arg ast.Exp } func isConvertibleToString(typ types.Type) bool { - return types.AssertableTo(errorType, typ) || stringerType != nil && types.AssertableTo(stringerType, typ) + if bt, ok := typ.(*types.Basic); ok && bt.Kind() == types.UntypedNil { + // We explicitly don't want untyped nil, which is + // convertible to both of the interfaces below, as it + // would just panic anyway. + return false + } + if types.ConvertibleTo(typ, errorType) { + return true // via .Error() + } + if stringerType != nil && types.ConvertibleTo(typ, stringerType) { + return true // via .String() + } + return false } // hasBasicType reports whether x's type is a types.Basic with the given kind. @@ -299,15 +310,4 @@ func (f *File) matchStructArgType(t printfArgType, typ *types.Struct, arg ast.Ex return true } -// hasMethod reports whether the type contains a method with the given name. -// It is part of the workaround for Formatters and should be deleted when -// that workaround is no longer necessary. -// TODO: This could be better once issue 6259 is fixed. -func (f *File) hasMethod(typ types.Type, name string) bool { - // assume we have an addressable variable of type typ - obj, _, _ := types.LookupFieldOrMethod(typ, true, f.pkg.typesPkg, name) - _, ok := obj.(*types.Func) - return ok -} - -var archSizes = types.SizesFor(runtime.Compiler, build.Default.GOARCH) +var archSizes = types.SizesFor("gc", build.Default.GOARCH) diff --git a/libgo/go/cmd/vet/vet_test.go b/libgo/go/cmd/vet/vet_test.go index 116b77e971b..3e42525e89b 100644 --- a/libgo/go/cmd/vet/vet_test.go +++ b/libgo/go/cmd/vet/vet_test.go @@ -6,12 +6,17 @@ package main_test import ( "bytes" + "errors" "fmt" "internal/testenv" + "io/ioutil" + "log" "os" "os/exec" "path/filepath" + "regexp" "runtime" + "strconv" "strings" "sync" "testing" @@ -19,7 +24,7 @@ import ( const ( dataDir = "testdata" - binary = "testvet.exe" + binary = "./testvet.exe" ) // We implement TestMain so remove the test binary when all is done. @@ -29,16 +34,6 @@ func TestMain(m *testing.M) { os.Exit(result) } -func MustHavePerl(t *testing.T) { - switch runtime.GOOS { - case "plan9", "windows": - t.Skipf("skipping test: perl not available on %s", runtime.GOOS) - } - if _, err := exec.LookPath("perl"); err != nil { - t.Skipf("skipping test: perl not found in path") - } -} - var ( buildMu sync.Mutex // guards following built = false // We have built the binary. @@ -55,7 +50,6 @@ func Build(t *testing.T) { t.Skip("cannot run on this environment") } testenv.MustHaveGoBuild(t) - MustHavePerl(t) cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", binary) output, err := cmd.CombinedOutput() if err != nil { @@ -67,26 +61,19 @@ func Build(t *testing.T) { } func Vet(t *testing.T, files []string) { - errchk := filepath.Join(runtime.GOROOT(), "test", "errchk") - if _, err := os.Stat(errchk); err != nil { - t.Skipf("skipping because no errchk: %v", err) - } flags := []string{ - "./" + binary, "-printfuncs=Warn:1,Warnf:1", "-all", "-shadow", } - cmd := exec.Command(errchk, append(flags, files...)...) - if !run(cmd, t) { - t.Fatal("vet command failed") - } + cmd := exec.Command(binary, append(flags, files...)...) + errchk(cmd, files, t) } -// Run this shell script, but do it in Go so it can be run by "go test". -// go build -o testvet -// $(GOROOT)/test/errchk ./testvet -shadow -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s -// rm testvet +// TestVet is equivalent to running this: +// go build -o ./testvet +// errorCheck the output of ./testvet -shadow -printfuncs='Warn:1,Warnf:1' testdata/*.go testdata/*.s +// rm ./testvet // // TestVet tests self-contained files in testdata/*.go. @@ -98,7 +85,6 @@ func TestVet(t *testing.T) { Build(t) t.Parallel() - // errchk ./testvet gos, err := filepath.Glob(filepath.Join(dataDir, "*.go")) if err != nil { t.Fatal(err) @@ -130,21 +116,23 @@ func TestVet(t *testing.T) { } func TestVetPrint(t *testing.T) { - Build(t) - errchk := filepath.Join(runtime.GOROOT(), "test", "errchk") - if _, err := os.Stat(errchk); err != nil { - t.Skipf("skipping because no errchk: %v", err) + if runtime.Compiler == "gccgo" { + // This test currently fails with gccgo because, in + // the absence of standard library sources, gccgo can + // not deduce that the standard log package formatting + // functions are just printf wrappers. + t.Skip("skipping for gccgo because there are no standard library sources") } + + Build(t) + file := filepath.Join("testdata", "print.go") cmd := exec.Command( - errchk, - "go", "vet", "-vettool=./"+binary, + "go", "vet", "-vettool="+binary, "-printf", "-printfuncs=Warn:1,Warnf:1", - "testdata/print.go", + file, ) - if !run(cmd, t) { - t.Fatal("vet command failed") - } + errchk(cmd, []string{file}, t) } func TestVetAsm(t *testing.T) { @@ -161,7 +149,6 @@ func TestVetAsm(t *testing.T) { } t.Parallel() - // errchk ./testvet Vet(t, append(gos, asms...)) } @@ -187,23 +174,20 @@ func TestVetDirs(t *testing.T) { } } -func run(c *exec.Cmd, t *testing.T) bool { +func errchk(c *exec.Cmd, files []string, t *testing.T) { output, err := c.CombinedOutput() - if err != nil { + if _, ok := err.(*exec.ExitError); !ok { t.Logf("vet output:\n%s", output) t.Fatal(err) } - // Errchk delights by not returning non-zero status if it finds errors, so we look at the output. - // It prints "BUG" if there is a failure. - if !c.ProcessState.Success() { - t.Logf("vet output:\n%s", output) - return false + fullshort := make([]string, 0, len(files)*2) + for _, f := range files { + fullshort = append(fullshort, f, filepath.Base(f)) } - ok := !bytes.Contains(output, []byte("BUG")) - if !ok { - t.Logf("vet output:\n%s", output) + err = errorCheck(string(output), false, fullshort...) + if err != nil { + t.Errorf("error check failed: %s", err) } - return ok } // TestTags verifies that the -tags argument controls which files to check. @@ -220,7 +204,7 @@ func TestTags(t *testing.T) { "-v", // We're going to look at the files it examines. "testdata/tagtest", } - cmd := exec.Command("./"+binary, args...) + cmd := exec.Command(binary, args...) output, err := cmd.CombinedOutput() if err != nil { t.Fatal(err) @@ -240,10 +224,225 @@ func TestTags(t *testing.T) { func TestVetVerbose(t *testing.T) { t.Parallel() Build(t) - cmd := exec.Command("./"+binary, "-v", "-all", "testdata/cgo/cgo3.go") + cmd := exec.Command(binary, "-v", "-all", "testdata/cgo/cgo3.go") out, err := cmd.CombinedOutput() if err != nil { t.Logf("%s", out) t.Error(err) } } + +// All declarations below were adapted from test/run.go. + +// errorCheck matches errors in outStr against comments in source files. +// For each line of the source files which should generate an error, +// there should be a comment of the form // ERROR "regexp". +// If outStr has an error for a line which has no such comment, +// this function will report an error. +// Likewise if outStr does not have an error for a line which has a comment, +// or if the error message does not match the . +// The syntax is Perl but its best to stick to egrep. +// +// Sources files are supplied as fullshort slice. +// It consists of pairs: full path to source file and it's base name. +func errorCheck(outStr string, wantAuto bool, fullshort ...string) (err error) { + var errs []error + out := splitOutput(outStr, wantAuto) + // Cut directory name. + for i := range out { + for j := 0; j < len(fullshort); j += 2 { + full, short := fullshort[j], fullshort[j+1] + out[i] = strings.Replace(out[i], full, short, -1) + } + } + + var want []wantedError + for j := 0; j < len(fullshort); j += 2 { + full, short := fullshort[j], fullshort[j+1] + want = append(want, wantedErrors(full, short)...) + } + for _, we := range want { + var errmsgs []string + if we.auto { + errmsgs, out = partitionStrings("", out) + } else { + errmsgs, out = partitionStrings(we.prefix, out) + } + if len(errmsgs) == 0 { + errs = append(errs, fmt.Errorf("%s:%d: missing error %q", we.file, we.lineNum, we.reStr)) + continue + } + matched := false + n := len(out) + for _, errmsg := range errmsgs { + // Assume errmsg says "file:line: foo". + // Cut leading "file:line: " to avoid accidental matching of file name instead of message. + text := errmsg + if i := strings.Index(text, " "); i >= 0 { + text = text[i+1:] + } + if we.re.MatchString(text) { + matched = true + } else { + out = append(out, errmsg) + } + } + if !matched { + errs = append(errs, fmt.Errorf("%s:%d: no match for %#q in:\n\t%s", we.file, we.lineNum, we.reStr, strings.Join(out[n:], "\n\t"))) + continue + } + } + + if len(out) > 0 { + errs = append(errs, fmt.Errorf("Unmatched Errors:")) + for _, errLine := range out { + errs = append(errs, fmt.Errorf("%s", errLine)) + } + } + + if len(errs) == 0 { + return nil + } + if len(errs) == 1 { + return errs[0] + } + var buf bytes.Buffer + fmt.Fprintf(&buf, "\n") + for _, err := range errs { + fmt.Fprintf(&buf, "%s\n", err.Error()) + } + return errors.New(buf.String()) +} + +func splitOutput(out string, wantAuto bool) []string { + // gc error messages continue onto additional lines with leading tabs. + // Split the output at the beginning of each line that doesn't begin with a tab. + // lines are impossible to match so those are filtered out. + var res []string + for _, line := range strings.Split(out, "\n") { + line = strings.TrimSuffix(line, "\r") // normalize Windows output + if strings.HasPrefix(line, "\t") { + res[len(res)-1] += "\n" + line + } else if strings.HasPrefix(line, "go tool") || strings.HasPrefix(line, "#") || !wantAuto && strings.HasPrefix(line, "") { + continue + } else if strings.TrimSpace(line) != "" { + res = append(res, line) + } + } + return res +} + +// matchPrefix reports whether s starts with file name prefix followed by a :, +// and possibly preceded by a directory name. +func matchPrefix(s, prefix string) bool { + i := strings.Index(s, ":") + if i < 0 { + return false + } + j := strings.LastIndex(s[:i], "/") + s = s[j+1:] + if len(s) <= len(prefix) || s[:len(prefix)] != prefix { + return false + } + if s[len(prefix)] == ':' { + return true + } + return false +} + +func partitionStrings(prefix string, strs []string) (matched, unmatched []string) { + for _, s := range strs { + if matchPrefix(s, prefix) { + matched = append(matched, s) + } else { + unmatched = append(unmatched, s) + } + } + return +} + +type wantedError struct { + reStr string + re *regexp.Regexp + lineNum int + auto bool // match line + file string + prefix string +} + +var ( + errRx = regexp.MustCompile(`// (?:GC_)?ERROR (.*)`) + errAutoRx = regexp.MustCompile(`// (?:GC_)?ERRORAUTO (.*)`) + errQuotesRx = regexp.MustCompile(`"([^"]*)"`) + lineRx = regexp.MustCompile(`LINE(([+-])([0-9]+))?`) +) + +// wantedErrors parses expected errors from comments in a file. +func wantedErrors(file, short string) (errs []wantedError) { + cache := make(map[string]*regexp.Regexp) + + src, err := ioutil.ReadFile(file) + if err != nil { + log.Fatal(err) + } + for i, line := range strings.Split(string(src), "\n") { + lineNum := i + 1 + if strings.Contains(line, "////") { + // double comment disables ERROR + continue + } + var auto bool + m := errAutoRx.FindStringSubmatch(line) + if m != nil { + auto = true + } else { + m = errRx.FindStringSubmatch(line) + } + if m == nil { + continue + } + all := m[1] + mm := errQuotesRx.FindAllStringSubmatch(all, -1) + if mm == nil { + log.Fatalf("%s:%d: invalid errchk line: %s", file, lineNum, line) + } + for _, m := range mm { + replacedOnce := false + rx := lineRx.ReplaceAllStringFunc(m[1], func(m string) string { + if replacedOnce { + return m + } + replacedOnce = true + n := lineNum + if strings.HasPrefix(m, "LINE+") { + delta, _ := strconv.Atoi(m[5:]) + n += delta + } else if strings.HasPrefix(m, "LINE-") { + delta, _ := strconv.Atoi(m[5:]) + n -= delta + } + return fmt.Sprintf("%s:%d", short, n) + }) + re := cache[rx] + if re == nil { + var err error + re, err = regexp.Compile(rx) + if err != nil { + log.Fatalf("%s:%d: invalid regexp \"%#q\" in ERROR line: %v", file, lineNum, rx, err) + } + cache[rx] = re + } + prefix := fmt.Sprintf("%s:%d", short, lineNum) + errs = append(errs, wantedError{ + reStr: rx, + re: re, + prefix: prefix, + auto: auto, + lineNum: lineNum, + file: short, + }) + } + } + + return +} diff --git a/libgo/go/compress/bzip2/bzip2.go b/libgo/go/compress/bzip2/bzip2.go index f07c7e81e87..c40129b9820 100644 --- a/libgo/go/compress/bzip2/bzip2.go +++ b/libgo/go/compress/bzip2/bzip2.go @@ -8,7 +8,7 @@ package bzip2 import "io" // There's no RFC for bzip2. I used the Wikipedia page for reference and a lot -// of guessing: http://en.wikipedia.org/wiki/Bzip2 +// of guessing: https://en.wikipedia.org/wiki/Bzip2 // The source code to pyflate was useful for debugging: // http://www.paul.sladen.org/projects/pyflate diff --git a/libgo/go/compress/bzip2/huffman.go b/libgo/go/compress/bzip2/huffman.go index dbba9a58b5a..36ae9540093 100644 --- a/libgo/go/compress/bzip2/huffman.go +++ b/libgo/go/compress/bzip2/huffman.go @@ -43,30 +43,34 @@ func (t *huffmanTree) Decode(br *bitReader) (v uint16) { if br.bits > 0 { // Get next bit - fast path. br.bits-- - bit = 0 - (uint16(br.n>>br.bits) & 1) + bit = uint16(br.n>>(br.bits&63)) & 1 } else { // Get next bit - slow path. // Use ReadBits to retrieve a single bit // from the underling io.ByteReader. - bit = 0 - uint16(br.ReadBits(1)) + bit = uint16(br.ReadBits(1)) } - // now - // bit = 0xffff if the next bit was 1 - // bit = 0x0000 if the next bit was 0 - // 1 means left, 0 means right. - // - // if bit == 0xffff { - // nodeIndex = node.left - // } else { - // nodeIndex = node.right - // } - nodeIndex = (bit & node.left) | (^bit & node.right) + // Trick a compiler into generating conditional move instead of branch, + // by making both loads unconditional. + l, r := node.left, node.right + + if bit == 1 { + nodeIndex = l + } else { + nodeIndex = r + } if nodeIndex == invalidNodeValue { // We found a leaf. Use the value of bit to decide // whether is a left or a right value. - return (bit & node.leftValue) | (^bit & node.rightValue) + l, r := node.leftValue, node.rightValue + if bit == 1 { + v = l + } else { + v = r + } + return } } } @@ -90,13 +94,24 @@ func newHuffmanTree(lengths []uint8) (huffmanTree, error) { // First we sort the code length assignments by ascending code length, // using the symbol value to break ties. - pairs := huffmanSymbolLengthPairs(make([]huffmanSymbolLengthPair, len(lengths))) + pairs := make([]huffmanSymbolLengthPair, len(lengths)) for i, length := range lengths { pairs[i].value = uint16(i) pairs[i].length = length } - sort.Sort(pairs) + sort.Slice(pairs, func(i, j int) bool { + if pairs[i].length < pairs[j].length { + return true + } + if pairs[i].length > pairs[j].length { + return false + } + if pairs[i].value < pairs[j].value { + return true + } + return false + }) // Now we assign codes to the symbols, starting with the longest code. // We keep the codes packed into a uint32, at the most-significant end. @@ -105,7 +120,7 @@ func newHuffmanTree(lengths []uint8) (huffmanTree, error) { code := uint32(0) length := uint8(32) - codes := huffmanCodes(make([]huffmanCode, len(lengths))) + codes := make([]huffmanCode, len(lengths)) for i := len(pairs) - 1; i >= 0; i-- { if length > pairs[i].length { length = pairs[i].length @@ -120,7 +135,9 @@ func newHuffmanTree(lengths []uint8) (huffmanTree, error) { // Now we can sort by the code so that the left half of each branch are // grouped together, recursively. - sort.Sort(codes) + sort.Slice(codes, func(i, j int) bool { + return codes[i].code < codes[j].code + }) t.nodes = make([]huffmanNode, len(codes)) _, err := buildHuffmanNode(&t, codes, 0) @@ -133,30 +150,6 @@ type huffmanSymbolLengthPair struct { length uint8 } -// huffmanSymbolLengthPair is used to provide an interface for sorting. -type huffmanSymbolLengthPairs []huffmanSymbolLengthPair - -func (h huffmanSymbolLengthPairs) Len() int { - return len(h) -} - -func (h huffmanSymbolLengthPairs) Less(i, j int) bool { - if h[i].length < h[j].length { - return true - } - if h[i].length > h[j].length { - return false - } - if h[i].value < h[j].value { - return true - } - return false -} - -func (h huffmanSymbolLengthPairs) Swap(i, j int) { - h[i], h[j] = h[j], h[i] -} - // huffmanCode contains a symbol, its code and code length. type huffmanCode struct { code uint32 @@ -164,21 +157,6 @@ type huffmanCode struct { value uint16 } -// huffmanCodes is used to provide an interface for sorting. -type huffmanCodes []huffmanCode - -func (n huffmanCodes) Len() int { - return len(n) -} - -func (n huffmanCodes) Less(i, j int) bool { - return n[i].code < n[j].code -} - -func (n huffmanCodes) Swap(i, j int) { - n[i], n[j] = n[j], n[i] -} - // buildHuffmanNode takes a slice of sorted huffmanCodes and builds a node in // the Huffman tree at the given level. It returns the index of the newly // constructed node. diff --git a/libgo/go/compress/flate/deflate.go b/libgo/go/compress/flate/deflate.go index 4d6a5357d88..8b92f1586db 100644 --- a/libgo/go/compress/flate/deflate.go +++ b/libgo/go/compress/flate/deflate.go @@ -720,7 +720,7 @@ func (w *Writer) Write(data []byte) (n int, err error) { // In the terminology of the zlib library, Flush is equivalent to Z_SYNC_FLUSH. func (w *Writer) Flush() error { // For more about flushing: - // http://www.bolet.org/~pornin/deflate-flush.html + // https://www.bolet.org/~pornin/deflate-flush.html return w.d.syncFlush() } diff --git a/libgo/go/compress/flate/inflate.go b/libgo/go/compress/flate/inflate.go index faa33cc6e9b..25e81f3f727 100644 --- a/libgo/go/compress/flate/inflate.go +++ b/libgo/go/compress/flate/inflate.go @@ -10,7 +10,7 @@ package flate import ( "bufio" "io" - mathbits "math/bits" + "math/bits" "strconv" "sync" ) @@ -113,7 +113,7 @@ type huffmanDecoder struct { // tree (i.e., neither over-subscribed nor under-subscribed). The exception is a // degenerate case where the tree has only a single symbol with length 1. Empty // trees are permitted. -func (h *huffmanDecoder) init(bits []int) bool { +func (h *huffmanDecoder) init(lengths []int) bool { // Sanity enables additional runtime tests during Huffman // table construction. It's intended to be used during // development to supplement the currently ad-hoc unit tests. @@ -127,7 +127,7 @@ func (h *huffmanDecoder) init(bits []int) bool { // compute min and max length. var count [maxCodeLen]int var min, max int - for _, n := range bits { + for _, n := range lengths { if n == 0 { continue } @@ -177,7 +177,7 @@ func (h *huffmanDecoder) init(bits []int) bool { link := nextcode[huffmanChunkBits+1] >> 1 h.links = make([][]uint32, huffmanNumChunks-link) for j := uint(link); j < huffmanNumChunks; j++ { - reverse := int(mathbits.Reverse16(uint16(j))) + reverse := int(bits.Reverse16(uint16(j))) reverse >>= uint(16 - huffmanChunkBits) off := j - uint(link) if sanity && h.chunks[reverse] != 0 { @@ -188,14 +188,14 @@ func (h *huffmanDecoder) init(bits []int) bool { } } - for i, n := range bits { + for i, n := range lengths { if n == 0 { continue } code := nextcode[n] nextcode[n]++ chunk := uint32(i<>= uint(16 - n) if n <= huffmanChunkBits { for off := reverse; off < len(h.chunks); off += 1 << uint(n) { @@ -557,7 +557,7 @@ readLiteral: return } } - dist = int(mathbits.Reverse8(uint8(f.b & 0x1F << 3))) + dist = int(bits.Reverse8(uint8(f.b & 0x1F << 3))) f.b >>= 5 f.nb -= 5 } else { @@ -629,10 +629,7 @@ func (f *decompressor) dataBlock() { nr, err := io.ReadFull(f.r, f.buf[0:4]) f.roffset += int64(nr) if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - f.err = err + f.err = noEOF(err) return } n := int(f.buf[0]) | int(f.buf[1])<<8 @@ -665,10 +662,7 @@ func (f *decompressor) copyData() { f.copyLen -= cnt f.dict.writeMark(cnt) if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - f.err = err + f.err = noEOF(err) return } @@ -690,13 +684,18 @@ func (f *decompressor) finishBlock() { f.step = (*decompressor).nextBlock } +// noEOF returns err, unless err == io.EOF, in which case it returns io.ErrUnexpectedEOF. +func noEOF(e error) error { + if e == io.EOF { + return io.ErrUnexpectedEOF + } + return e +} + func (f *decompressor) moreBits() error { c, err := f.r.ReadByte() if err != nil { - if err == io.EOF { - err = io.ErrUnexpectedEOF - } - return err + return noEOF(err) } f.roffset++ f.b |= uint32(c) << f.nb @@ -711,25 +710,37 @@ func (f *decompressor) huffSym(h *huffmanDecoder) (int, error) { // cases, the chunks slice will be 0 for the invalid sequence, leading it // satisfy the n == 0 check below. n := uint(h.min) + // Optimization. Compiler isn't smart enough to keep f.b,f.nb in registers, + // but is smart enough to keep local variables in registers, so use nb and b, + // inline call to moreBits and reassign b,nb back to f on return. + nb, b := f.nb, f.b for { - for f.nb < n { - if err := f.moreBits(); err != nil { - return 0, err + for nb < n { + c, err := f.r.ReadByte() + if err != nil { + f.b = b + f.nb = nb + return 0, noEOF(err) } + f.roffset++ + b |= uint32(c) << (nb & 31) + nb += 8 } - chunk := h.chunks[f.b&(huffmanNumChunks-1)] + chunk := h.chunks[b&(huffmanNumChunks-1)] n = uint(chunk & huffmanCountMask) if n > huffmanChunkBits { - chunk = h.links[chunk>>huffmanValueShift][(f.b>>huffmanChunkBits)&h.linkMask] + chunk = h.links[chunk>>huffmanValueShift][(b>>huffmanChunkBits)&h.linkMask] n = uint(chunk & huffmanCountMask) } - if n <= f.nb { + if n <= nb { if n == 0 { + f.b = b + f.nb = nb f.err = CorruptInputError(f.roffset) return 0, f.err } - f.b >>= n - f.nb -= n + f.b = b >> (n & 31) + f.nb = nb - n return int(chunk >> huffmanValueShift), nil } } diff --git a/libgo/go/compress/gzip/gzip.go b/libgo/go/compress/gzip/gzip.go index 0cc44c59e0f..eaeb1857954 100644 --- a/libgo/go/compress/gzip/gzip.go +++ b/libgo/go/compress/gzip/gzip.go @@ -41,7 +41,7 @@ type Writer struct { // NewWriter returns a new Writer. // Writes to the returned writer are compressed and written to w. // -// It is the caller's responsibility to call Close on the WriteCloser when done. +// It is the caller's responsibility to call Close on the Writer when done. // Writes may be buffered and not flushed until Close. // // Callers that wish to set the fields in Writer.Header must do so before @@ -165,26 +165,26 @@ func (z *Writer) Write(p []byte) (int, error) { z.buf[8] = 4 } z.buf[9] = z.OS - n, z.err = z.w.Write(z.buf[:10]) + _, z.err = z.w.Write(z.buf[:10]) if z.err != nil { - return n, z.err + return 0, z.err } if z.Extra != nil { z.err = z.writeBytes(z.Extra) if z.err != nil { - return n, z.err + return 0, z.err } } if z.Name != "" { z.err = z.writeString(z.Name) if z.err != nil { - return n, z.err + return 0, z.err } } if z.Comment != "" { z.err = z.writeString(z.Comment) if z.err != nil { - return n, z.err + return 0, z.err } } if z.compressor == nil { diff --git a/libgo/go/compress/gzip/gzip_test.go b/libgo/go/compress/gzip/gzip_test.go index 865c529f55c..e16aba1572d 100644 --- a/libgo/go/compress/gzip/gzip_test.go +++ b/libgo/go/compress/gzip/gzip_test.go @@ -7,6 +7,7 @@ package gzip import ( "bufio" "bytes" + "io" "io/ioutil" "reflect" "testing" @@ -233,3 +234,40 @@ func TestWriterReset(t *testing.T) { t.Errorf("buf2 %q != original buf of %q", buf2.String(), buf.String()) } } + +type limitedWriter struct { + N int +} + +func (l *limitedWriter) Write(p []byte) (n int, err error) { + if n := l.N; n < len(p) { + l.N = 0 + return n, io.ErrShortWrite + } + l.N -= len(p) + return len(p), nil +} + +// Write should never return more bytes than the input slice. +func TestLimitedWrite(t *testing.T) { + msg := []byte("a") + + for lim := 2; lim < 20; lim++ { + z := NewWriter(&limitedWriter{lim}) + if n, _ := z.Write(msg); n > len(msg) { + t.Errorf("Write() = %d, want %d or less", n, len(msg)) + } + + z.Reset(&limitedWriter{lim}) + z.Header = Header{ + Comment: "comment", + Extra: []byte("extra"), + ModTime: time.Now(), + Name: "name", + OS: 1, + } + if n, _ := z.Write(msg); n > len(msg) { + t.Errorf("Write() = %d, want %d or less", n, len(msg)) + } + } +} diff --git a/libgo/go/compress/gzip/issue14937_test.go b/libgo/go/compress/gzip/issue14937_test.go index 30c1390dfd7..7a19672d578 100644 --- a/libgo/go/compress/gzip/issue14937_test.go +++ b/libgo/go/compress/gzip/issue14937_test.go @@ -21,6 +21,10 @@ func TestGZIPFilesHaveZeroMTimes(t *testing.T) { if testenv.Builder() == "" { t.Skip("skipping test on non-builder") } + if !testenv.HasSrc() { + t.Skip("skipping; no GOROOT available") + } + goroot, err := filepath.EvalSymlinks(runtime.GOROOT()) if err != nil { t.Fatal("error evaluating GOROOT: ", err) diff --git a/libgo/go/compress/lzw/reader_test.go b/libgo/go/compress/lzw/reader_test.go index f8974de28fc..98bbfbb763e 100644 --- a/libgo/go/compress/lzw/reader_test.go +++ b/libgo/go/compress/lzw/reader_test.go @@ -66,7 +66,7 @@ var lzwTests = []lzwTest{ "\x54\x9e\x08\x29\xf2\x44\x8a\x93\x27\x54\x04", io.ErrUnexpectedEOF, }, - // This example comes from http://en.wikipedia.org/wiki/Graphics_Interchange_Format. + // This example comes from https://en.wikipedia.org/wiki/Graphics_Interchange_Format. { "gif;LSB;8", "\x28\xff\xff\xff\x28\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", diff --git a/libgo/go/compress/zlib/reader_test.go b/libgo/go/compress/zlib/reader_test.go index 7e27aecb47d..70e33babd10 100644 --- a/libgo/go/compress/zlib/reader_test.go +++ b/libgo/go/compress/zlib/reader_test.go @@ -19,7 +19,7 @@ type zlibTest struct { } // Compare-to-golden test data was generated by the ZLIB example program at -// http://www.zlib.net/zpipe.c +// https://www.zlib.net/zpipe.c var zlibTests = []zlibTest{ { diff --git a/libgo/go/compress/zlib/writer.go b/libgo/go/compress/zlib/writer.go index 1620c00c523..a7b219467ee 100644 --- a/libgo/go/compress/zlib/writer.go +++ b/libgo/go/compress/zlib/writer.go @@ -38,7 +38,7 @@ type Writer struct { // NewWriter creates a new Writer. // Writes to the returned Writer are compressed and written to w. // -// It is the caller's responsibility to call Close on the WriteCloser when done. +// It is the caller's responsibility to call Close on the Writer when done. // Writes may be buffered and not flushed until Close. func NewWriter(w io.Writer) *Writer { z, _ := NewWriterLevelDict(w, DefaultCompression, nil) diff --git a/libgo/go/container/heap/heap.go b/libgo/go/container/heap/heap.go index b2c64276c82..67b5efcac7e 100644 --- a/libgo/go/container/heap/heap.go +++ b/libgo/go/container/heap/heap.go @@ -18,7 +18,9 @@ package heap import "sort" -// Any type that implements heap.Interface may be used as a +// The Interface type describes the requirements +// for a type using the routines in this package. +// Any type that implements it may be used as a // min-heap with the following invariants (established after // Init has been called or if the data is empty or sorted): // @@ -33,11 +35,10 @@ type Interface interface { Pop() interface{} // remove and return element Len() - 1. } -// A heap must be initialized before any of the heap operations -// can be used. Init is idempotent with respect to the heap invariants +// Init establishes the heap invariants required by the other routines in this package. +// Init is idempotent with respect to the heap invariants // and may be called whenever the heap invariants may have been invalidated. // Its complexity is O(n) where n = h.Len(). -// func Init(h Interface) { // heapify n := h.Len() diff --git a/libgo/go/context/benchmark_test.go b/libgo/go/context/benchmark_test.go index 3c526dd1069..5d56863050a 100644 --- a/libgo/go/context/benchmark_test.go +++ b/libgo/go/context/benchmark_test.go @@ -13,6 +13,30 @@ import ( "time" ) +func BenchmarkCommonParentCancel(b *testing.B) { + root := WithValue(Background(), "key", "value") + shared, sharedcancel := WithCancel(root) + defer sharedcancel() + + b.ResetTimer() + b.RunParallel(func(pb *testing.PB) { + x := 0 + for pb.Next() { + ctx, cancel := WithCancel(shared) + if ctx.Value("key").(string) != "value" { + b.Fatal("should not be reached") + } + for i := 0; i < 100; i++ { + x /= x + 1 + } + cancel() + for i := 0; i < 100; i++ { + x /= x + 1 + } + } + }) +} + func BenchmarkWithTimeout(b *testing.B) { for concurrency := 40; concurrency <= 4e5; concurrency *= 100 { name := fmt.Sprintf("concurrency=%d", concurrency) @@ -96,3 +120,21 @@ func buildContextTree(root Context, depth int) { root, _ = WithCancel(root) } } + +func BenchmarkCheckCanceled(b *testing.B) { + ctx, cancel := WithCancel(Background()) + cancel() + b.Run("Err", func(b *testing.B) { + for i := 0; i < b.N; i++ { + ctx.Err() + } + }) + b.Run("Done", func(b *testing.B) { + for i := 0; i < b.N; i++ { + select { + case <-ctx.Done(): + default: + } + } + }) +} diff --git a/libgo/go/context/context.go b/libgo/go/context/context.go index 06580e0465a..1b4fa41b8cc 100644 --- a/libgo/go/context/context.go +++ b/libgo/go/context/context.go @@ -334,8 +334,9 @@ func (c *cancelCtx) Done() <-chan struct{} { func (c *cancelCtx) Err() error { c.mu.Lock() - defer c.mu.Unlock() - return c.err + err := c.err + c.mu.Unlock() + return err } func (c *cancelCtx) String() string { diff --git a/libgo/go/context/example_test.go b/libgo/go/context/example_test.go index b2c2aa921da..2b28b577042 100644 --- a/libgo/go/context/example_test.go +++ b/libgo/go/context/example_test.go @@ -93,6 +93,8 @@ func ExampleWithTimeout() { // context deadline exceeded } +// This example demonstrates how a value can be passed to the context +// and also how to retrieve it if it exists. func ExampleWithValue() { type favContextKey string diff --git a/libgo/go/crypto/aes/aes_gcm.go b/libgo/go/crypto/aes/aes_gcm.go index 3e5e2359d86..3888010025f 100644 --- a/libgo/go/crypto/aes/aes_gcm.go +++ b/libgo/go/crypto/aes/aes_gcm.go @@ -3,21 +3,18 @@ // license that can be found in the LICENSE file. // +build ignore -// -build amd64 +// -build amd64 arm64 package aes import ( "crypto/cipher" + subtleoverlap "crypto/internal/subtle" "crypto/subtle" "errors" ) -// The following functions are defined in gcm_amd64.s. -func hasGCMAsm() bool - -//go:noescape -func aesEncBlock(dst, src *[16]byte, ks []uint32) +// The following functions are defined in gcm_*.s. //go:noescape func gcmAesInit(productTable *[256]byte, ks []uint32) @@ -37,6 +34,7 @@ func gcmAesFinish(productTable *[256]byte, tagMask, T *[16]byte, pLen, dLen uint const ( gcmBlockSize = 16 gcmTagSize = 16 + gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. gcmStandardNonceSize = 12 ) @@ -54,8 +52,8 @@ var _ gcmAble = (*aesCipherGCM)(nil) // NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only // called by crypto/cipher.NewGCM via the gcmAble interface. -func (c *aesCipherGCM) NewGCM(nonceSize int) (cipher.AEAD, error) { - g := &gcmAsm{ks: c.enc, nonceSize: nonceSize} +func (c *aesCipherGCM) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { + g := &gcmAsm{ks: c.enc, nonceSize: nonceSize, tagSize: tagSize} gcmAesInit(&g.productTable, g.ks) return g, nil } @@ -69,14 +67,16 @@ type gcmAsm struct { productTable [256]byte // nonceSize contains the expected size of the nonce, in bytes. nonceSize int + // tagSize contains the size of the tag, in bytes. + tagSize int } func (g *gcmAsm) NonceSize() int { return g.nonceSize } -func (*gcmAsm) Overhead() int { - return gcmTagSize +func (g *gcmAsm) Overhead() int { + return g.tagSize } // sliceForAppend takes a slice and a requested number of bytes. It returns a @@ -98,10 +98,10 @@ func sliceForAppend(in []byte, n int) (head, tail []byte) { // details. func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { if len(nonce) != g.nonceSize { - panic("cipher: incorrect nonce length given to GCM") + panic("crypto/cipher: incorrect nonce length given to GCM") } if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { - panic("cipher: message too large for GCM") + panic("crypto/cipher: message too large for GCM") } var counter, tagMask [gcmBlockSize]byte @@ -116,12 +116,15 @@ func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) } - aesEncBlock(&tagMask, &counter, g.ks) + encryptBlockAsm(len(g.ks)/4-1, &g.ks[0], &tagMask[0], &counter[0]) var tagOut [gcmTagSize]byte gcmAesData(&g.productTable, data, &tagOut) - ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize) + ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) + if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) { + panic("crypto/cipher: invalid buffer overlap") + } if len(plaintext) > 0 { gcmAesEnc(&g.productTable, out, plaintext, &counter, &tagOut, g.ks) } @@ -135,18 +138,23 @@ func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { // for details. func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { if len(nonce) != g.nonceSize { - panic("cipher: incorrect nonce length given to GCM") + panic("crypto/cipher: incorrect nonce length given to GCM") + } + // Sanity check to prevent the authentication from always succeeding if an implementation + // leaves tagSize uninitialized, for example. + if g.tagSize < gcmMinimumTagSize { + panic("crypto/cipher: incorrect GCM tag size") } - if len(ciphertext) < gcmTagSize { + if len(ciphertext) < g.tagSize { return nil, errOpen } - if uint64(len(ciphertext)) > ((1<<32)-2)*BlockSize+gcmTagSize { + if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { return nil, errOpen } - tag := ciphertext[len(ciphertext)-gcmTagSize:] - ciphertext = ciphertext[:len(ciphertext)-gcmTagSize] + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] // See GCM spec, section 7.1. var counter, tagMask [gcmBlockSize]byte @@ -161,18 +169,21 @@ func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) } - aesEncBlock(&tagMask, &counter, g.ks) + encryptBlockAsm(len(g.ks)/4-1, &g.ks[0], &tagMask[0], &counter[0]) var expectedTag [gcmTagSize]byte gcmAesData(&g.productTable, data, &expectedTag) ret, out := sliceForAppend(dst, len(ciphertext)) + if subtleoverlap.InexactOverlap(out, ciphertext) { + panic("crypto/cipher: invalid buffer overlap") + } if len(ciphertext) > 0 { gcmAesDec(&g.productTable, out, ciphertext, &counter, &expectedTag, g.ks) } gcmAesFinish(&g.productTable, &tagMask, &expectedTag, uint64(len(ciphertext)), uint64(len(data))) - if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 { + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { for i := range out { out[i] = 0 } diff --git a/libgo/go/crypto/aes/aes_test.go b/libgo/go/crypto/aes/aes_test.go index 28144968fcf..bedc2da9465 100644 --- a/libgo/go/crypto/aes/aes_test.go +++ b/libgo/go/crypto/aes/aes_test.go @@ -122,7 +122,7 @@ func TestTd(t *testing.T) { } // Test vectors are from FIPS 197: -// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf +// https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf // Appendix A of FIPS 197: Key expansion examples type KeyTest struct { diff --git a/libgo/go/crypto/aes/block.go b/libgo/go/crypto/aes/block.go index 41ea9cf95ed..8647019d580 100644 --- a/libgo/go/crypto/aes/block.go +++ b/libgo/go/crypto/aes/block.go @@ -31,8 +31,8 @@ // // See FIPS 197 for specification, and see Daemen and Rijmen's Rijndael submission // for implementation details. -// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf -// http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf +// https://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf +// https://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf package aes diff --git a/libgo/go/crypto/aes/cbc_s390x.go b/libgo/go/crypto/aes/cbc_s390x.go index 6b011b28b5f..67e928e2d20 100644 --- a/libgo/go/crypto/aes/cbc_s390x.go +++ b/libgo/go/crypto/aes/cbc_s390x.go @@ -8,6 +8,7 @@ package aes import ( "crypto/cipher" + "crypto/internal/subtle" ) // Assert that aesCipherAsm implements the cbcEncAble and cbcDecAble interfaces. @@ -50,6 +51,9 @@ func (x *cbc) CryptBlocks(dst, src []byte) { if len(dst) < len(src) { panic("crypto/cipher: output smaller than input") } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } if len(src) > 0 { cryptBlocksChain(x.c, &x.iv[0], &x.b.key[0], &dst[0], &src[0], len(src)) } diff --git a/libgo/go/crypto/aes/cipher.go b/libgo/go/crypto/aes/cipher.go index c5a8e91d009..bb93fbb36e2 100644 --- a/libgo/go/crypto/aes/cipher.go +++ b/libgo/go/crypto/aes/cipher.go @@ -6,6 +6,7 @@ package aes import ( "crypto/cipher" + "crypto/internal/subtle" "strconv" ) @@ -57,6 +58,9 @@ func (c *aesCipher) Encrypt(dst, src []byte) { if len(dst) < BlockSize { panic("crypto/aes: output not full block") } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } encryptBlockGo(c.enc, dst, src) } @@ -67,5 +71,8 @@ func (c *aesCipher) Decrypt(dst, src []byte) { if len(dst) < BlockSize { panic("crypto/aes: output not full block") } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } decryptBlockGo(c.dec, dst, src) } diff --git a/libgo/go/crypto/aes/cipher_amd64.go b/libgo/go/crypto/aes/cipher_asm.go similarity index 75% rename from libgo/go/crypto/aes/cipher_amd64.go rename to libgo/go/crypto/aes/cipher_asm.go index fbd157e49e7..dc4251acc3d 100644 --- a/libgo/go/crypto/aes/cipher_amd64.go +++ b/libgo/go/crypto/aes/cipher_asm.go @@ -2,33 +2,42 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build ignore +// +build ignore_for_gccgo +// +build amd64 arm64 package aes import ( "crypto/cipher" - "crypto/internal/cipherhw" + "crypto/internal/subtle" + "internal/cpu" ) -// defined in asm_amd64.s +// defined in asm_*.s + +//go:noescape func encryptBlockAsm(nr int, xk *uint32, dst, src *byte) + +//go:noescape func decryptBlockAsm(nr int, xk *uint32, dst, src *byte) + +//go:noescape func expandKeyAsm(nr int, key *byte, enc *uint32, dec *uint32) type aesCipherAsm struct { aesCipher } -var useAsm = cipherhw.AESGCMSupport() +var supportsAES = cpu.X86.HasAES || cpu.ARM64.HasAES +var supportsGFMUL = cpu.X86.HasPCLMULQDQ || cpu.ARM64.HasPMULL func newCipher(key []byte) (cipher.Block, error) { - if !useAsm { + if !supportsAES { return newCipherGeneric(key) } n := len(key) + 28 c := aesCipherAsm{aesCipher{make([]uint32, n), make([]uint32, n)}} - rounds := 10 + var rounds int switch len(key) { case 128 / 8: rounds = 10 @@ -37,11 +46,11 @@ func newCipher(key []byte) (cipher.Block, error) { case 256 / 8: rounds = 14 } + expandKeyAsm(rounds, &key[0], &c.enc[0], &c.dec[0]) - if hasGCMAsm() { + if supportsAES && supportsGFMUL { return &aesCipherGCM{c}, nil } - return &c, nil } @@ -54,6 +63,9 @@ func (c *aesCipherAsm) Encrypt(dst, src []byte) { if len(dst) < BlockSize { panic("crypto/aes: output not full block") } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } encryptBlockAsm(len(c.enc)/4-1, &c.enc[0], &dst[0], &src[0]) } @@ -64,13 +76,16 @@ func (c *aesCipherAsm) Decrypt(dst, src []byte) { if len(dst) < BlockSize { panic("crypto/aes: output not full block") } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } decryptBlockAsm(len(c.dec)/4-1, &c.dec[0], &dst[0], &src[0]) } // expandKey is used by BenchmarkExpand to ensure that the asm implementation // of key expansion is used for the benchmark when it is available. func expandKey(key []byte, enc, dec []uint32) { - if useAsm { + if supportsAES { rounds := 10 // rounds needed for AES128 switch len(key) { case 192 / 8: diff --git a/libgo/go/crypto/aes/cipher_generic.go b/libgo/go/crypto/aes/cipher_generic.go index 98169bf5fd7..19a930f09d8 100644 --- a/libgo/go/crypto/aes/cipher_generic.go +++ b/libgo/go/crypto/aes/cipher_generic.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. -// -build !amd64,!s390x,!ppc64le +// -build !amd64,!s390x,!ppc64le,!arm64 package aes diff --git a/libgo/go/crypto/aes/cipher_ppc64le.go b/libgo/go/crypto/aes/cipher_ppc64le.go index 1d16fe03f04..599ea82f70f 100644 --- a/libgo/go/crypto/aes/cipher_ppc64le.go +++ b/libgo/go/crypto/aes/cipher_ppc64le.go @@ -8,28 +8,24 @@ package aes import ( "crypto/cipher" + "crypto/internal/subtle" ) // defined in asm_ppc64le.s //go:noescape - func setEncryptKeyAsm(key *byte, keylen int, enc *uint32) int //go:noescape - func setDecryptKeyAsm(key *byte, keylen int, dec *uint32) int //go:noescape - func doEncryptKeyAsm(key *byte, keylen int, dec *uint32) int //go:noescape - func encryptBlockAsm(dst, src *byte, enc *uint32) //go:noescape - func decryptBlockAsm(dst, src *byte, dec *uint32) type aesCipherAsm struct { @@ -61,6 +57,9 @@ func (c *aesCipherAsm) Encrypt(dst, src []byte) { if len(dst) < BlockSize { panic("crypto/aes: output not full block") } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } encryptBlockAsm(&dst[0], &src[0], &c.enc[0]) } @@ -71,6 +70,9 @@ func (c *aesCipherAsm) Decrypt(dst, src []byte) { if len(dst) < BlockSize { panic("crypto/aes: output not full block") } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } decryptBlockAsm(&dst[0], &src[0], &c.dec[0]) } diff --git a/libgo/go/crypto/aes/cipher_s390x.go b/libgo/go/crypto/aes/cipher_s390x.go index 253ce893892..b885a45e75e 100644 --- a/libgo/go/crypto/aes/cipher_s390x.go +++ b/libgo/go/crypto/aes/cipher_s390x.go @@ -8,7 +8,8 @@ package aes import ( "crypto/cipher" - "crypto/internal/cipherhw" + "crypto/internal/subtle" + "internal/cpu" ) type code int @@ -21,9 +22,9 @@ const ( ) type aesCipherAsm struct { - function code // code for cipher message instruction - key []byte // key (128, 192 or 256 bytes) - storage [256]byte // array backing key slice + function code // code for cipher message instruction + key []byte // key (128, 192 or 256 bits) + storage [32]byte // array backing key slice } // cryptBlocks invokes the cipher message (KM) instruction with @@ -32,10 +33,12 @@ type aesCipherAsm struct { //go:noescape func cryptBlocks(c code, key, dst, src *byte, length int) -var useAsm = cipherhw.AESGCMSupport() - func newCipher(key []byte) (cipher.Block, error) { - if !useAsm { + // The aesCipherAsm type implements the cbcEncAble, cbcDecAble, + // ctrAble and gcmAble interfaces. We therefore need to check + // for all the features required to implement these modes. + // Keep in sync with crypto/tls/common.go. + if !(cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR && (cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)) { return newCipherGeneric(key) } @@ -67,6 +70,9 @@ func (c *aesCipherAsm) Encrypt(dst, src []byte) { if len(dst) < BlockSize { panic("crypto/aes: output not full block") } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } cryptBlocks(c.function, &c.key[0], &dst[0], &src[0], BlockSize) } @@ -77,6 +83,9 @@ func (c *aesCipherAsm) Decrypt(dst, src []byte) { if len(dst) < BlockSize { panic("crypto/aes: output not full block") } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/aes: invalid buffer overlap") + } // The decrypt function code is equal to the function code + 128. cryptBlocks(c.function+128, &c.key[0], &dst[0], &src[0], BlockSize) } diff --git a/libgo/go/crypto/aes/const.go b/libgo/go/crypto/aes/const.go index cbac5ff0ea1..4eca4b9aff8 100644 --- a/libgo/go/crypto/aes/const.go +++ b/libgo/go/crypto/aes/const.go @@ -15,7 +15,7 @@ package aes // This file contains AES constants - 8720 bytes of initialized data. -// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf +// https://csrc.nist.gov/publications/fips/fips197/fips-197.pdf // AES is based on the mathematical behavior of binary polynomials // (polynomials over GF(2)) modulo the irreducible polynomial x⁸ + x⁴ + x³ + x + 1. diff --git a/libgo/go/crypto/aes/ctr_s390x.go b/libgo/go/crypto/aes/ctr_s390x.go index 7892f79d243..a3c43a326bb 100644 --- a/libgo/go/crypto/aes/ctr_s390x.go +++ b/libgo/go/crypto/aes/ctr_s390x.go @@ -8,6 +8,7 @@ package aes import ( "crypto/cipher" + "crypto/internal/subtle" "unsafe" ) @@ -66,9 +67,11 @@ func (c *aesctr) refill() { } func (c *aesctr) XORKeyStream(dst, src []byte) { - if len(src) > 0 { - // Assert len(dst) >= len(src) - _ = dst[len(src)-1] + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") } for len(src) > 0 { if len(c.buffer) == 0 { diff --git a/libgo/go/crypto/aes/gcm_s390x.go b/libgo/go/crypto/aes/gcm_s390x.go index ba6d7ce7665..18b0e82158d 100644 --- a/libgo/go/crypto/aes/gcm_s390x.go +++ b/libgo/go/crypto/aes/gcm_s390x.go @@ -8,8 +8,10 @@ package aes import ( "crypto/cipher" + subtleoverlap "crypto/internal/subtle" "crypto/subtle" "errors" + "internal/cpu" ) // This file contains two implementations of AES-GCM. The first implementation @@ -60,11 +62,13 @@ type gcmAsm struct { block *aesCipherAsm hashKey gcmHashKey nonceSize int + tagSize int } const ( gcmBlockSize = 16 gcmTagSize = 16 + gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. gcmStandardNonceSize = 12 ) @@ -75,15 +79,16 @@ var _ gcmAble = (*aesCipherAsm)(nil) // NewGCM returns the AES cipher wrapped in Galois Counter Mode. This is only // called by crypto/cipher.NewGCM via the gcmAble interface. -func (c *aesCipherAsm) NewGCM(nonceSize int) (cipher.AEAD, error) { +func (c *aesCipherAsm) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { var hk gcmHashKey c.Encrypt(hk[:], hk[:]) g := gcmAsm{ block: c, hashKey: hk, nonceSize: nonceSize, + tagSize: tagSize, } - if hasKMA { + if cpu.S390X.HasAESGCM { g := gcmKMA{g} return &g, nil } @@ -94,8 +99,8 @@ func (g *gcmAsm) NonceSize() int { return g.nonceSize } -func (*gcmAsm) Overhead() int { - return gcmTagSize +func (g *gcmAsm) Overhead() int { + return g.tagSize } // sliceForAppend takes a slice and a requested number of bytes. It returns a @@ -218,13 +223,16 @@ func (g *gcmAsm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSi // details. func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { if len(nonce) != g.nonceSize { - panic("cipher: incorrect nonce length given to GCM") + panic("crypto/cipher: incorrect nonce length given to GCM") } if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { - panic("cipher: message too large for GCM") + panic("crypto/cipher: message too large for GCM") } - ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize) + ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) + if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) { + panic("crypto/cipher: invalid buffer overlap") + } counter := g.deriveCounter(nonce) @@ -232,8 +240,10 @@ func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { g.block.Encrypt(tagMask[:], counter[:]) counter.inc() + var tagOut [gcmTagSize]byte g.counterCrypt(out, plaintext, &counter) - g.auth(out[len(plaintext):], out[:len(plaintext)], data, &tagMask) + g.auth(tagOut[:], out[:len(plaintext)], data, &tagMask) + copy(out[len(plaintext):], tagOut[:]) return ret } @@ -242,17 +252,22 @@ func (g *gcmAsm) Seal(dst, nonce, plaintext, data []byte) []byte { // for details. func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { if len(nonce) != g.nonceSize { - panic("cipher: incorrect nonce length given to GCM") + panic("crypto/cipher: incorrect nonce length given to GCM") } - if len(ciphertext) < gcmTagSize { + // Sanity check to prevent the authentication from always succeeding if an implementation + // leaves tagSize uninitialized, for example. + if g.tagSize < gcmMinimumTagSize { + panic("crypto/cipher: incorrect GCM tag size") + } + if len(ciphertext) < g.tagSize { return nil, errOpen } - if uint64(len(ciphertext)) > ((1<<32)-2)*BlockSize+gcmTagSize { + if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { return nil, errOpen } - tag := ciphertext[len(ciphertext)-gcmTagSize:] - ciphertext = ciphertext[:len(ciphertext)-gcmTagSize] + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] counter := g.deriveCounter(nonce) @@ -264,8 +279,11 @@ func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { g.auth(expectedTag[:], ciphertext, data, &tagMask) ret, out := sliceForAppend(dst, len(ciphertext)) + if subtleoverlap.InexactOverlap(out, ciphertext) { + panic("crypto/cipher: invalid buffer overlap") + } - if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 { + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { // The AESNI code decrypts and authenticates concurrently, and // so overwrites dst in the event of a tag mismatch. That // behavior is mimicked here in order to be consistent across @@ -280,13 +298,6 @@ func (g *gcmAsm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { return ret, nil } -// supportsKMA reports whether the message-security-assist 8 facility is available. -// This function call may be expensive so hasKMA should be queried instead. -func supportsKMA() bool - -// hasKMA contains the result of supportsKMA. -var hasKMA = supportsKMA() - // gcmKMA implements the cipher.AEAD interface using the KMA instruction. It should // only be used if hasKMA is true. type gcmKMA struct { @@ -312,13 +323,16 @@ func kmaGCM(fn code, key, dst, src, aad []byte, tag *[16]byte, cnt *gcmCount) // details. func (g *gcmKMA) Seal(dst, nonce, plaintext, data []byte) []byte { if len(nonce) != g.nonceSize { - panic("cipher: incorrect nonce length given to GCM") + panic("crypto/cipher: incorrect nonce length given to GCM") } if uint64(len(plaintext)) > ((1<<32)-2)*BlockSize { - panic("cipher: message too large for GCM") + panic("crypto/cipher: message too large for GCM") } - ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize) + ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) + if subtleoverlap.InexactOverlap(out[:len(plaintext)], plaintext) { + panic("crypto/cipher: invalid buffer overlap") + } counter := g.deriveCounter(nonce) fc := g.block.function | kmaLAAD | kmaLPC @@ -334,18 +348,25 @@ func (g *gcmKMA) Seal(dst, nonce, plaintext, data []byte) []byte { // for details. func (g *gcmKMA) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { if len(nonce) != g.nonceSize { - panic("cipher: incorrect nonce length given to GCM") + panic("crypto/cipher: incorrect nonce length given to GCM") } - if len(ciphertext) < gcmTagSize { + if len(ciphertext) < g.tagSize { return nil, errOpen } - if uint64(len(ciphertext)) > ((1<<32)-2)*BlockSize+gcmTagSize { + if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(BlockSize)+uint64(g.tagSize) { return nil, errOpen } - tag := ciphertext[len(ciphertext)-gcmTagSize:] - ciphertext = ciphertext[:len(ciphertext)-gcmTagSize] + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] ret, out := sliceForAppend(dst, len(ciphertext)) + if subtleoverlap.InexactOverlap(out, ciphertext) { + panic("crypto/cipher: invalid buffer overlap") + } + + if g.tagSize < gcmMinimumTagSize { + panic("crypto/cipher: incorrect GCM tag size") + } counter := g.deriveCounter(nonce) fc := g.block.function | kmaLAAD | kmaLPC | kmaDecrypt @@ -353,7 +374,7 @@ func (g *gcmKMA) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { var expectedTag [gcmTagSize]byte kmaGCM(fc, g.block.key, out[:len(ciphertext)], ciphertext, data, &expectedTag, &counter) - if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 { + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { // The AESNI code decrypts and authenticates concurrently, and // so overwrites dst in the event of a tag mismatch. That // behavior is mimicked here in order to be consistent across diff --git a/libgo/go/crypto/aes/modes.go b/libgo/go/crypto/aes/modes.go index 1623fc16e22..5c0b08eb6d8 100644 --- a/libgo/go/crypto/aes/modes.go +++ b/libgo/go/crypto/aes/modes.go @@ -12,7 +12,7 @@ import ( // implementation of GCM through the AEAD interface. // See crypto/cipher/gcm.go. type gcmAble interface { - NewGCM(size int) (cipher.AEAD, error) + NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) } // cbcEncAble is implemented by cipher.Blocks that can provide an optimized diff --git a/libgo/go/crypto/aes/modes_test.go b/libgo/go/crypto/aes/modes_test.go index 8c2e5f0560a..a3364c9b51b 100644 --- a/libgo/go/crypto/aes/modes_test.go +++ b/libgo/go/crypto/aes/modes_test.go @@ -25,7 +25,7 @@ type testBlock struct{} func (*testBlock) BlockSize() int { return 0 } func (*testBlock) Encrypt(a, b []byte) {} func (*testBlock) Decrypt(a, b []byte) {} -func (*testBlock) NewGCM(int) (cipher.AEAD, error) { +func (*testBlock) NewGCM(int, int) (cipher.AEAD, error) { return &testAEAD{}, nil } func (*testBlock) NewCBCEncrypter([]byte) cipher.BlockMode { diff --git a/libgo/go/crypto/cipher/cbc.go b/libgo/go/crypto/cipher/cbc.go index 0367d5971a6..0d07192e291 100644 --- a/libgo/go/crypto/cipher/cbc.go +++ b/libgo/go/crypto/cipher/cbc.go @@ -11,6 +11,8 @@ package cipher +import "crypto/internal/subtle" + type cbc struct { b Block blockSize int @@ -59,6 +61,9 @@ func (x *cbcEncrypter) CryptBlocks(dst, src []byte) { if len(dst) < len(src) { panic("crypto/cipher: output smaller than input") } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } iv := x.iv @@ -116,6 +121,9 @@ func (x *cbcDecrypter) CryptBlocks(dst, src []byte) { if len(dst) < len(src) { panic("crypto/cipher: output smaller than input") } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } if len(src) == 0 { return } diff --git a/libgo/go/crypto/cipher/cfb.go b/libgo/go/crypto/cipher/cfb.go index 9b4eebf5b45..80c9bc24ea0 100644 --- a/libgo/go/crypto/cipher/cfb.go +++ b/libgo/go/crypto/cipher/cfb.go @@ -6,6 +6,8 @@ package cipher +import "crypto/internal/subtle" + type cfb struct { b Block next []byte @@ -16,6 +18,12 @@ type cfb struct { } func (x *cfb) XORKeyStream(dst, src []byte) { + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } for len(src) > 0 { if x.outUsed == len(x.out) { x.b.Encrypt(x.out, x.next) diff --git a/libgo/go/crypto/cipher/cfb_test.go b/libgo/go/crypto/cipher/cfb_test.go index 9b544bb2118..ecb716df015 100644 --- a/libgo/go/crypto/cipher/cfb_test.go +++ b/libgo/go/crypto/cipher/cfb_test.go @@ -14,7 +14,7 @@ import ( ) // cfbTests contains the test vectors from -// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section +// https://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section // F.3.13. var cfbTests = []struct { key, iv, plaintext, ciphertext string diff --git a/libgo/go/crypto/cipher/cipher.go b/libgo/go/crypto/cipher/cipher.go index 31c14d7f914..7e1a4de9a37 100644 --- a/libgo/go/crypto/cipher/cipher.go +++ b/libgo/go/crypto/cipher/cipher.go @@ -4,7 +4,7 @@ // Package cipher implements standard block cipher modes that can be wrapped // around low-level block cipher implementations. -// See http://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html +// See https://csrc.nist.gov/groups/ST/toolkit/BCM/current_modes.html // and NIST Special Publication 800-38A. package cipher diff --git a/libgo/go/crypto/cipher/ctr.go b/libgo/go/crypto/cipher/ctr.go index 75f46cfe512..cba028d2a44 100644 --- a/libgo/go/crypto/cipher/ctr.go +++ b/libgo/go/crypto/cipher/ctr.go @@ -12,6 +12,8 @@ package cipher +import "crypto/internal/subtle" + type ctr struct { b Block ctr []byte @@ -71,6 +73,12 @@ func (x *ctr) refill() { } func (x *ctr) XORKeyStream(dst, src []byte) { + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } for len(src) > 0 { if x.outUsed >= len(x.out)-x.b.BlockSize() { x.refill() diff --git a/libgo/go/crypto/cipher/gcm.go b/libgo/go/crypto/cipher/gcm.go index 28f3ddd6e63..6321e9e82d3 100644 --- a/libgo/go/crypto/cipher/gcm.go +++ b/libgo/go/crypto/cipher/gcm.go @@ -5,6 +5,7 @@ package cipher import ( + subtleoverlap "crypto/internal/subtle" "crypto/subtle" "errors" ) @@ -26,8 +27,8 @@ type AEAD interface { // slice. The nonce must be NonceSize() bytes long and unique for all // time, for a given key. // - // The plaintext and dst must overlap exactly or not at all. To reuse - // plaintext's storage for the encrypted output, use plaintext[:0] as dst. + // To reuse plaintext's storage for the encrypted output, use plaintext[:0] + // as dst. Otherwise, the remaining capacity of dst must not overlap plaintext. Seal(dst, nonce, plaintext, additionalData []byte) []byte // Open decrypts and authenticates ciphertext, authenticates the @@ -36,8 +37,8 @@ type AEAD interface { // bytes long and both it and the additional data must match the // value passed to Seal. // - // The ciphertext and dst must overlap exactly or not at all. To reuse - // ciphertext's storage for the decrypted output, use ciphertext[:0] as dst. + // To reuse ciphertext's storage for the decrypted output, use ciphertext[:0] + // as dst. Otherwise, the remaining capacity of dst must not overlap plaintext. // // Even if the function fails, the contents of dst, up to its capacity, // may be overwritten. @@ -48,7 +49,7 @@ type AEAD interface { // implementation of GCM, like crypto/aes. NewGCM will check for this interface // and return the specific AEAD if found. type gcmAble interface { - NewGCM(int) (AEAD, error) + NewGCM(nonceSize, tagSize int) (AEAD, error) } // gcmFieldElement represents a value in GF(2¹²⁸). In order to reflect the GCM @@ -63,10 +64,11 @@ type gcmFieldElement struct { } // gcm represents a Galois Counter Mode with a specific key. See -// http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf +// https://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf type gcm struct { cipher Block nonceSize int + tagSize int // productTable contains the first sixteen powers of the key, H. // However, they are in bit reversed order. See NewGCMWithNonceSize. productTable [16]gcmFieldElement @@ -79,7 +81,7 @@ type gcm struct { // An exception is when the underlying Block was created by aes.NewCipher // on systems with hardware support for AES. See the crypto/aes package documentation for details. func NewGCM(cipher Block) (AEAD, error) { - return NewGCMWithNonceSize(cipher, gcmStandardNonceSize) + return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, gcmTagSize) } // NewGCMWithNonceSize returns the given 128-bit, block cipher wrapped in Galois @@ -89,8 +91,28 @@ func NewGCM(cipher Block) (AEAD, error) { // cryptosystem that uses non-standard nonce lengths. All other users should use // NewGCM, which is faster and more resistant to misuse. func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) { + return newGCMWithNonceAndTagSize(cipher, size, gcmTagSize) +} + +// NewGCMWithTagSize returns the given 128-bit, block cipher wrapped in Galois +// Counter Mode, which generates tags with the given length. +// +// Tag sizes between 12 and 16 bytes are allowed. +// +// Only use this function if you require compatibility with an existing +// cryptosystem that uses non-standard tag lengths. All other users should use +// NewGCM, which is more resistant to misuse. +func NewGCMWithTagSize(cipher Block, tagSize int) (AEAD, error) { + return newGCMWithNonceAndTagSize(cipher, gcmStandardNonceSize, tagSize) +} + +func newGCMWithNonceAndTagSize(cipher Block, nonceSize, tagSize int) (AEAD, error) { + if tagSize < gcmMinimumTagSize || tagSize > gcmBlockSize { + return nil, errors.New("cipher: incorrect tag size given to GCM") + } + if cipher, ok := cipher.(gcmAble); ok { - return cipher.NewGCM(size) + return cipher.NewGCM(nonceSize, tagSize) } if cipher.BlockSize() != gcmBlockSize { @@ -100,7 +122,7 @@ func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) { var key [gcmBlockSize]byte cipher.Encrypt(key[:], key[:]) - g := &gcm{cipher: cipher, nonceSize: size} + g := &gcm{cipher: cipher, nonceSize: nonceSize, tagSize: tagSize} // We precompute 16 multiples of |key|. However, when we do lookups // into this table we'll be using bits from a field element and @@ -124,6 +146,7 @@ func NewGCMWithNonceSize(cipher Block, size int) (AEAD, error) { const ( gcmBlockSize = 16 gcmTagSize = 16 + gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes. gcmStandardNonceSize = 12 ) @@ -131,19 +154,22 @@ func (g *gcm) NonceSize() int { return g.nonceSize } -func (*gcm) Overhead() int { - return gcmTagSize +func (g *gcm) Overhead() int { + return g.tagSize } func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte { if len(nonce) != g.nonceSize { - panic("cipher: incorrect nonce length given to GCM") + panic("crypto/cipher: incorrect nonce length given to GCM") } if uint64(len(plaintext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize()) { - panic("cipher: message too large for GCM") + panic("crypto/cipher: message too large for GCM") } - ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize) + ret, out := sliceForAppend(dst, len(plaintext)+g.tagSize) + if subtleoverlap.InexactOverlap(out, plaintext) { + panic("crypto/cipher: invalid buffer overlap") + } var counter, tagMask [gcmBlockSize]byte g.deriveCounter(&counter, nonce) @@ -152,7 +178,10 @@ func (g *gcm) Seal(dst, nonce, plaintext, data []byte) []byte { gcmInc32(&counter) g.counterCrypt(out, plaintext, &counter) - g.auth(out[len(plaintext):], out[:len(plaintext)], data, &tagMask) + + var tag [gcmTagSize]byte + g.auth(tag[:], out[:len(plaintext)], data, &tagMask) + copy(out[len(plaintext):], tag[:]) return ret } @@ -161,18 +190,23 @@ var errOpen = errors.New("cipher: message authentication failed") func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { if len(nonce) != g.nonceSize { - panic("cipher: incorrect nonce length given to GCM") + panic("crypto/cipher: incorrect nonce length given to GCM") + } + // Sanity check to prevent the authentication from always succeeding if an implementation + // leaves tagSize uninitialized, for example. + if g.tagSize < gcmMinimumTagSize { + panic("crypto/cipher: incorrect GCM tag size") } - if len(ciphertext) < gcmTagSize { + if len(ciphertext) < g.tagSize { return nil, errOpen } - if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize())+gcmTagSize { + if uint64(len(ciphertext)) > ((1<<32)-2)*uint64(g.cipher.BlockSize())+uint64(g.tagSize) { return nil, errOpen } - tag := ciphertext[len(ciphertext)-gcmTagSize:] - ciphertext = ciphertext[:len(ciphertext)-gcmTagSize] + tag := ciphertext[len(ciphertext)-g.tagSize:] + ciphertext = ciphertext[:len(ciphertext)-g.tagSize] var counter, tagMask [gcmBlockSize]byte g.deriveCounter(&counter, nonce) @@ -184,8 +218,11 @@ func (g *gcm) Open(dst, nonce, ciphertext, data []byte) ([]byte, error) { g.auth(expectedTag[:], ciphertext, data, &tagMask) ret, out := sliceForAppend(dst, len(ciphertext)) + if subtleoverlap.InexactOverlap(out, ciphertext) { + panic("crypto/cipher: invalid buffer overlap") + } - if subtle.ConstantTimeCompare(expectedTag[:], tag) != 1 { + if subtle.ConstantTimeCompare(expectedTag[:g.tagSize], tag) != 1 { // The AESNI code decrypts and authenticates concurrently, and // so overwrites dst in the event of a tag mismatch. That // behavior is mimicked here in order to be consistent across @@ -387,6 +424,7 @@ func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize] } func getUint64(data []byte) uint64 { + _ = data[7] // bounds check hint to compiler; see golang.org/issue/14808 r := uint64(data[0])<<56 | uint64(data[1])<<48 | uint64(data[2])<<40 | @@ -399,6 +437,7 @@ func getUint64(data []byte) uint64 { } func putUint64(out []byte, v uint64) { + _ = out[7] // bounds check hint to compiler; see golang.org/issue/14808 out[0] = byte(v >> 56) out[1] = byte(v >> 48) out[2] = byte(v >> 40) diff --git a/libgo/go/crypto/cipher/gcm_test.go b/libgo/go/crypto/cipher/gcm_test.go index 6878b4cb42b..64d5cc0db4f 100644 --- a/libgo/go/crypto/cipher/gcm_test.go +++ b/libgo/go/crypto/cipher/gcm_test.go @@ -188,6 +188,35 @@ var aesGCMTests = []struct { "0feccdfae8ed65fa31a0858a1c466f79e8aa658c2f3ba93c3f92158b4e30955e1c62580450beff", "b69a7e17bb5af688883274550a4ded0d1aff49a0b18343f4b382f745c163f7f714c9206a32a1ff012427e19431951edd0a755e5f491b0eedfd7df68bbc6085dd2888607a2f998c3e881eb1694109250db28291e71f4ad344a125624fb92e16ea9815047cd1111cabfdc9cb8c3b4b0f40aa91d31774009781231400789ed545404af6c3f76d07ddc984a7bd8f52728159782832e298cc4d529be96d17be898efd83e44dc7b0e2efc645849fd2bba61fef0ae7be0dcab233cc4e2b7ba4e887de9c64b97f2a1818aa54371a8d629dae37975f7784e5e3cc77055ed6e975b1e5f55e6bbacdc9f295ce4ada2c16113cd5b323cf78b7dde39f4a87aa8c141a31174e3584ccbd380cf5ec6d1dba539928b084fa9683e9c0953acf47cc3ac384a2c38914f1da01fb2cfd78905c2b58d36b2574b9df15535d82", }, + // These cases test non-standard tag sizes. + { + "89c54b0d3bc3c397d5039058c220685f", + "bc7f45c00868758d62d4bb4d", + "582670b0baf5540a3775b6615605bd05", + "48d16cda0337105a50e2ed76fd18e114", + "fc2d4c4eee2209ddbba6663c02765e6955e783b00156f5da0446e2970b877f", + }, + { + "bad6049678bf75c9087b3e3ae7e72c13", + "a0a017b83a67d8f1b883e561", + "a1be93012f05a1958440f74a5311f4a1", + "f7c27b51d5367161dc2ff1e9e3edc6f2", + "36f032f7e3dc3275ca22aedcdc68436b99a2227f8bb69d45ea5d8842cd08", + }, + { + "66a3c722ccf9709525650973ecc100a9", + "1621d42d3a6d42a2d2bf9494", + "61fa9dbbed2190fbc2ffabf5d2ea4ff8", + "d7a9b6523b8827068a6354a6d166c6b9", + "fef3b20f40e08a49637cc82f4c89b8603fd5c0132acfab97b5fff651c4", + }, + { + "562ae8aadb8d23e0f271a99a7d1bd4d1", + "f7a5e2399413b89b6ad31aff", + "bbdc3504d803682aa08a773cde5f231a", + "2b9680b886b3efb7c6354b38c63b5373", + "e2b7e5ed5ff27fc8664148f5a628a46dcbf2015184fffb82f2651c36", + }, } func TestAESGCM(t *testing.T) { @@ -201,9 +230,29 @@ func TestAESGCM(t *testing.T) { nonce, _ := hex.DecodeString(test.nonce) plaintext, _ := hex.DecodeString(test.plaintext) ad, _ := hex.DecodeString(test.ad) - aesgcm, err := cipher.NewGCMWithNonceSize(aes, len(nonce)) - if err != nil { - t.Fatal(err) + tagSize := (len(test.result) - len(test.plaintext)) / 2 + + var aesgcm cipher.AEAD + switch { + // Handle non-standard nonce sizes + case tagSize != 16: + aesgcm, err = cipher.NewGCMWithTagSize(aes, tagSize) + if err != nil { + t.Fatal(err) + } + + // Handle non-standard tag sizes + case len(nonce) != 12: + aesgcm, err = cipher.NewGCMWithNonceSize(aes, len(nonce)) + if err != nil { + t.Fatal(err) + } + + default: + aesgcm, err = cipher.NewGCM(aes) + if err != nil { + t.Fatal(err) + } } ct := aesgcm.Seal(nil, nonce, plaintext, ad) @@ -245,6 +294,19 @@ func TestAESGCM(t *testing.T) { } } +func TestGCMInvalidTagSize(t *testing.T) { + key, _ := hex.DecodeString("ab72c77b97cb5fe9a382d9fe81ffdbed") + + aes, _ := aes.NewCipher(key) + + for _, tagSize := range []int{0, 1, aes.BlockSize() + 1} { + aesgcm, err := cipher.NewGCMWithTagSize(aes, tagSize) + if aesgcm != nil || err == nil { + t.Fatalf("NewGCMWithNonceAndTagSize was successful with an invalid %d-byte tag size", tagSize) + } + } +} + func TestTagFailureOverwrite(t *testing.T) { // The AESNI GCM code decrypts and authenticates concurrently and so // overwrites the output buffer before checking the authentication tag. @@ -362,7 +424,7 @@ func TestGCMAsm(t *testing.T) { // generate permutations type pair struct{ align, length int } - lengths := []int{0, 8192, 8193, 8208} + lengths := []int{0, 156, 8192, 8193, 8208} keySizes := []int{16, 24, 32} alignments := []int{0, 1, 2, 3} if testing.Short() { diff --git a/libgo/go/crypto/cipher/ofb.go b/libgo/go/crypto/cipher/ofb.go index 7b35f8995c8..fc477248658 100644 --- a/libgo/go/crypto/cipher/ofb.go +++ b/libgo/go/crypto/cipher/ofb.go @@ -6,6 +6,8 @@ package cipher +import "crypto/internal/subtle" + type ofb struct { b Block cipher []byte @@ -54,6 +56,12 @@ func (x *ofb) refill() { } func (x *ofb) XORKeyStream(dst, src []byte) { + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } for len(src) > 0 { if x.outUsed >= len(x.out)-x.b.BlockSize() { x.refill() diff --git a/libgo/go/crypto/des/cipher.go b/libgo/go/crypto/des/cipher.go index 46af5b0f022..9e6779c216b 100644 --- a/libgo/go/crypto/des/cipher.go +++ b/libgo/go/crypto/des/cipher.go @@ -6,6 +6,7 @@ package des import ( "crypto/cipher" + "crypto/internal/subtle" "encoding/binary" "strconv" ) @@ -37,9 +38,31 @@ func NewCipher(key []byte) (cipher.Block, error) { func (c *desCipher) BlockSize() int { return BlockSize } -func (c *desCipher) Encrypt(dst, src []byte) { encryptBlock(c.subkeys[:], dst, src) } +func (c *desCipher) Encrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/des: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/des: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/des: invalid buffer overlap") + } + encryptBlock(c.subkeys[:], dst, src) +} -func (c *desCipher) Decrypt(dst, src []byte) { decryptBlock(c.subkeys[:], dst, src) } +func (c *desCipher) Decrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/des: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/des: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/des: invalid buffer overlap") + } + decryptBlock(c.subkeys[:], dst, src) +} // A tripleDESCipher is an instance of TripleDES encryption. type tripleDESCipher struct { @@ -62,6 +85,16 @@ func NewTripleDESCipher(key []byte) (cipher.Block, error) { func (c *tripleDESCipher) BlockSize() int { return BlockSize } func (c *tripleDESCipher) Encrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/des: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/des: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/des: invalid buffer overlap") + } + b := binary.BigEndian.Uint64(src) b = permuteInitialBlock(b) left, right := uint32(b>>32), uint32(b) @@ -87,6 +120,16 @@ func (c *tripleDESCipher) Encrypt(dst, src []byte) { } func (c *tripleDESCipher) Decrypt(dst, src []byte) { + if len(src) < BlockSize { + panic("crypto/des: input not full block") + } + if len(dst) < BlockSize { + panic("crypto/des: output not full block") + } + if subtle.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { + panic("crypto/des: invalid buffer overlap") + } + b := binary.BigEndian.Uint64(src) b = permuteInitialBlock(b) left, right := uint32(b>>32), uint32(b) diff --git a/libgo/go/crypto/dsa/dsa.go b/libgo/go/crypto/dsa/dsa.go index e94585579eb..575314b1b46 100644 --- a/libgo/go/crypto/dsa/dsa.go +++ b/libgo/go/crypto/dsa/dsa.go @@ -11,6 +11,8 @@ import ( "errors" "io" "math/big" + + "crypto/internal/randutil" ) // Parameters represents the domain parameters for a key. These parameters can @@ -195,6 +197,8 @@ func fermatInverse(k, P *big.Int) *big.Int { // Be aware that calling Sign with an attacker-controlled PrivateKey may // require an arbitrary amount of CPU. func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { + randutil.MaybeReadByte(rand) + // FIPS 186-3, section 4.6 n := priv.Q.BitLen() diff --git a/libgo/go/crypto/ecdsa/ecdsa.go b/libgo/go/crypto/ecdsa/ecdsa.go index 755ed284a91..2bab14cbb9e 100644 --- a/libgo/go/crypto/ecdsa/ecdsa.go +++ b/libgo/go/crypto/ecdsa/ecdsa.go @@ -26,6 +26,8 @@ import ( "errors" "io" "math/big" + + "crypto/internal/randutil" ) // A invertible implements fast inverse mod Curve.Params().N @@ -152,6 +154,8 @@ var errZeroParam = errors.New("zero parameter") // returns the signature as a pair of integers. The security of the private key // depends on the entropy of rand. func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { + randutil.MaybeReadByte(rand) + // Get min(log2(q) / 2, 256) bits of entropy from rand. entropylen := (priv.Curve.Params().BitSize + 7) / 16 if entropylen > 32 { diff --git a/libgo/go/crypto/ecdsa/ecdsa_test.go b/libgo/go/crypto/ecdsa/ecdsa_test.go index 9224a039f3f..6284e06bd43 100644 --- a/libgo/go/crypto/ecdsa/ecdsa_test.go +++ b/libgo/go/crypto/ecdsa/ecdsa_test.go @@ -213,7 +213,7 @@ func fromHex(s string) *big.Int { func TestVectors(t *testing.T) { // This test runs the full set of NIST test vectors from - // http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip + // https://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip // // The SigVer.rsp file has been edited to remove test vectors for // unsupported algorithms and has been compressed. diff --git a/libgo/go/crypto/ecdsa/example_test.go b/libgo/go/crypto/ecdsa/example_test.go new file mode 100644 index 00000000000..7c7fb1b27b1 --- /dev/null +++ b/libgo/go/crypto/ecdsa/example_test.go @@ -0,0 +1,34 @@ +// 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 gccgo_examples + +package ecdsa_test + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/sha256" + "fmt" +) + +func Example() { + privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + panic(err) + } + + msg := "hello, world" + hash := sha256.Sum256([]byte(msg)) + + r, s, err := ecdsa.Sign(rand.Reader, privateKey, hash[:]) + if err != nil { + panic(err) + } + fmt.Printf("signature: (0x%x, 0x%x)\n", r, s) + + valid := ecdsa.Verify(&privateKey.PublicKey, hash[:], r, s) + fmt.Println("signature verified:", valid) +} diff --git a/libgo/go/crypto/elliptic/elliptic.go b/libgo/go/crypto/elliptic/elliptic.go index 35aacf24e51..4fc2b5e5213 100644 --- a/libgo/go/crypto/elliptic/elliptic.go +++ b/libgo/go/crypto/elliptic/elliptic.go @@ -20,7 +20,7 @@ import ( ) // A Curve represents a short-form Weierstrass curve with a=-3. -// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html +// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html type Curve interface { // Params returns the parameters for the curve. Params() *CurveParams @@ -108,7 +108,7 @@ func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { // addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and // (x2, y2, z2) and returns their sum, also in Jacobian form. func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) { - // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl + // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl x3, y3, z3 := new(big.Int), new(big.Int), new(big.Int) if z1.Sign() == 0 { x3.Set(x2) @@ -191,7 +191,7 @@ func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { // doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and // returns its double, also in Jacobian form. func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) { - // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b + // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b delta := new(big.Int).Mul(z, z) delta.Mod(delta, curve.P) gamma := new(big.Int).Mul(y, y) diff --git a/libgo/go/crypto/elliptic/elliptic_test.go b/libgo/go/crypto/elliptic/elliptic_test.go index f661359c358..09c5483520e 100644 --- a/libgo/go/crypto/elliptic/elliptic_test.go +++ b/libgo/go/crypto/elliptic/elliptic_test.go @@ -608,7 +608,7 @@ func TestUnmarshalToLargeCoordinates(t *testing.T) { copy(invalidX[33:], y.Bytes()) if X, Y := Unmarshal(curve, invalidX); X != nil || Y != nil { - t.Errorf("Unmarshal accpets invalid X coordinate") + 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. @@ -625,6 +625,6 @@ func TestUnmarshalToLargeCoordinates(t *testing.T) { copy(invalidY[33:], y.Bytes()) if X, Y := Unmarshal(curve, invalidY); X != nil || Y != nil { - t.Errorf("Unmarshal accpets invalid Y coordinate") + t.Errorf("Unmarshal accepts invalid Y coordinate") } } diff --git a/libgo/go/crypto/elliptic/fuzz_test.go b/libgo/go/crypto/elliptic/fuzz_test.go new file mode 100644 index 00000000000..10196cf0bc9 --- /dev/null +++ b/libgo/go/crypto/elliptic/fuzz_test.go @@ -0,0 +1,54 @@ +// 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 amd64 arm64 + +package elliptic + +import ( + "crypto/rand" + "testing" + "time" +) + +func TestFuzz(t *testing.T) { + + p256 := P256() + p256Generic := p256.Params() + + var scalar1 [32]byte + var scalar2 [32]byte + var timeout *time.Timer + + if testing.Short() { + timeout = time.NewTimer(500 * time.Millisecond) + } else { + timeout = time.NewTimer(2 * time.Second) + } + + for { + select { + case <-timeout.C: + return + default: + } + + rand.Read(scalar1[:]) + rand.Read(scalar2[:]) + + x, y := p256.ScalarBaseMult(scalar1[:]) + x2, y2 := p256Generic.ScalarBaseMult(scalar1[:]) + + xx, yy := p256.ScalarMult(x, y, scalar2[:]) + xx2, yy2 := p256Generic.ScalarMult(x2, y2, scalar2[:]) + + if x.Cmp(x2) != 0 || y.Cmp(y2) != 0 { + t.Fatalf("ScalarBaseMult does not match reference result with scalar: %x, please report this error to security@golang.org", scalar1) + } + + if xx.Cmp(xx2) != 0 || yy.Cmp(yy2) != 0 { + t.Fatalf("ScalarMult does not match reference result with scalars: %x and %x, please report this error to security@golang.org", scalar1, scalar2) + } + } +} diff --git a/libgo/go/crypto/elliptic/p224.go b/libgo/go/crypto/elliptic/p224.go index 22d0e2429cd..2ea63f3f0c0 100644 --- a/libgo/go/crypto/elliptic/p224.go +++ b/libgo/go/crypto/elliptic/p224.go @@ -7,7 +7,7 @@ package elliptic // This is a constant-time, 32-bit implementation of P224. See FIPS 186-3, // section D.2.2. // -// See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background. +// See https://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background. import ( "math/big" @@ -503,7 +503,7 @@ func p224Contract(out, in *p224FieldElement) { // p224AddJacobian computes *out = a+b where a != b. func p224AddJacobian(x3, y3, z3, x1, y1, z1, x2, y2, z2 *p224FieldElement) { - // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-p224Add-2007-bl + // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-p224Add-2007-bl var z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v p224FieldElement var c p224LargeFieldElement diff --git a/libgo/go/crypto/elliptic/p256.go b/libgo/go/crypto/elliptic/p256.go index a0933dc6fb1..937d2a4afea 100644 --- a/libgo/go/crypto/elliptic/p256.go +++ b/libgo/go/crypto/elliptic/p256.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. -// -build !amd64 +// -build !amd64,!arm64 package elliptic @@ -817,7 +817,7 @@ func p256Scalar8(out *[p256Limbs]uint32) { // p256PointDouble sets {xOut,yOut,zOut} = 2*{x,y,z}. // -// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l +// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l func p256PointDouble(xOut, yOut, zOut, x, y, z *[p256Limbs]uint32) { var delta, gamma, alpha, beta, tmp, tmp2 [p256Limbs]uint32 @@ -850,7 +850,7 @@ func p256PointDouble(xOut, yOut, zOut, x, y, z *[p256Limbs]uint32) { // p256PointAddMixed sets {xOut,yOut,zOut} = {x1,y1,z1} + {x2,y2,1}. // (i.e. the second point is affine.) // -// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl +// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl // // Note that this function does not handle P+P, infinity+P nor P+infinity // correctly. @@ -886,7 +886,7 @@ func p256PointAddMixed(xOut, yOut, zOut, x1, y1, z1, x2, y2 *[p256Limbs]uint32) // p256PointAdd sets {xOut,yOut,zOut} = {x1,y1,z1} + {x2,y2,z2}. // -// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl +// See https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl // // Note that this function does not handle P+P, infinity+P nor P+infinity // correctly. diff --git a/libgo/go/crypto/elliptic/p256_amd64.go b/libgo/go/crypto/elliptic/p256_asm.go similarity index 82% rename from libgo/go/crypto/elliptic/p256_amd64.go rename to libgo/go/crypto/elliptic/p256_asm.go index f108e737e02..aee065b3833 100644 --- a/libgo/go/crypto/elliptic/p256_amd64.go +++ b/libgo/go/crypto/elliptic/p256_asm.go @@ -7,11 +7,11 @@ // detail in: // S.Gueron and V.Krasnov, "Fast prime field elliptic-curve cryptography with // 256-bit primes" -// http://link.springer.com/article/10.1007%2Fs13389-014-0090-x +// https://link.springer.com/article/10.1007%2Fs13389-014-0090-x // https://eprint.iacr.org/2013/816.pdf -// +build ignore -// +build amd64 +// +build ignore_for_gccgo +// +build amd64 arm64 package elliptic @@ -32,7 +32,7 @@ type ( var ( p256 p256Curve - p256Precomputed *[37][64 * 8]uint64 + p256Precomputed *[43][32 * 8]uint64 precomputeOnce sync.Once ) @@ -51,14 +51,14 @@ func (curve p256Curve) Params() *CurveParams { return curve.CurveParams } -// Functions implemented in p256_asm_amd64.s +// Functions implemented in p256_asm_*64.s // Montgomery multiplication modulo P256 //go:noescape func p256Mul(res, in1, in2 []uint64) -// Montgomery square modulo P256 +// Montgomery square modulo P256, repeated n times (n >= 1) //go:noescape -func p256Sqr(res, in []uint64) +func p256Sqr(res, in []uint64, n int) // Montgomery multiplication by 1 //go:noescape @@ -122,11 +122,20 @@ func (curve p256Curve) Inverse(k *big.Int) *big.Int { k = new(big.Int).Mod(k, p256.N) } - // table will store precomputed powers of x. The four words at index - // 4×i store x^(i+1). - var table [4 * 15]uint64 + // table will store precomputed powers of x. + var table [4 * 9]uint64 + var ( + _1 = table[4*0 : 4*1] + _11 = table[4*1 : 4*2] + _101 = table[4*2 : 4*3] + _111 = table[4*3 : 4*4] + _1111 = table[4*4 : 4*5] + _10101 = table[4*5 : 4*6] + _101111 = table[4*6 : 4*7] + x = table[4*7 : 4*8] + t = table[4*8 : 4*9] + ) - x := make([]uint64, 4) fromBig(x[:], k) // This code operates in the Montgomery domain where R = 2^256 mod n // and n is the order of the scalar field. (See initP256 for the @@ -134,53 +143,49 @@ func (curve p256Curve) Inverse(k *big.Int) *big.Int { // multiplication of x and y in the calculates (x × y × R^-1) mod n. RR // is R×R mod n thus the Montgomery multiplication x and RR gives x×R, // i.e. converts x into the Montgomery domain. + // Window values borrowed from https://briansmith.org/ecc-inversion-addition-chains-01#p256_scalar_inversion RR := []uint64{0x83244c95be79eea2, 0x4699799c49bd6fa6, 0x2845b2392b6bec59, 0x66e12d94f3d95620} - p256OrdMul(table[:4], x, RR) + p256OrdMul(_1, x, RR) // _1 + p256OrdSqr(x, _1, 1) // _10 + p256OrdMul(_11, x, _1) // _11 + p256OrdMul(_101, x, _11) // _101 + p256OrdMul(_111, x, _101) // _111 + p256OrdSqr(x, _101, 1) // _1010 + p256OrdMul(_1111, _101, x) // _1111 - // Prepare the table, no need in constant time access, because the - // power is not a secret. (Entry 0 is never used.) - for i := 2; i < 16; i += 2 { - p256OrdSqr(table[4*(i-1):], table[4*((i/2)-1):], 1) - p256OrdMul(table[4*i:], table[4*(i-1):], table[:4]) - } + p256OrdSqr(t, x, 1) // _10100 + p256OrdMul(_10101, t, _1) // _10101 + p256OrdSqr(x, _10101, 1) // _101010 + p256OrdMul(_101111, _101, x) // _101111 + p256OrdMul(x, _10101, x) // _111111 = x6 + p256OrdSqr(t, x, 2) // _11111100 + p256OrdMul(t, t, _11) // _11111111 = x8 + p256OrdSqr(x, t, 8) // _ff00 + p256OrdMul(x, x, t) // _ffff = x16 + p256OrdSqr(t, x, 16) // _ffff0000 + p256OrdMul(t, t, x) // _ffffffff = x32 - x[0] = table[4*14+0] // f - x[1] = table[4*14+1] - x[2] = table[4*14+2] - x[3] = table[4*14+3] + p256OrdSqr(x, t, 64) + p256OrdMul(x, x, t) + p256OrdSqr(x, x, 32) + p256OrdMul(x, x, t) - p256OrdSqr(x, x, 4) - p256OrdMul(x, x, table[4*14:4*14+4]) // ff - t := make([]uint64, 4, 4) - t[0] = x[0] - t[1] = x[1] - t[2] = x[2] - t[3] = x[3] + sqrs := []uint8{ + 6, 5, 4, 5, 5, + 4, 3, 3, 5, 9, + 6, 2, 5, 6, 5, + 4, 5, 5, 3, 10, + 2, 5, 5, 3, 7, 6} + muls := [][]uint64{ + _101111, _111, _11, _1111, _10101, + _101, _101, _101, _111, _101111, + _1111, _1, _1, _1111, _111, + _111, _111, _101, _11, _101111, + _11, _11, _11, _1, _10101, _1111} - p256OrdSqr(x, x, 8) - p256OrdMul(x, x, t) // ffff - t[0] = x[0] - t[1] = x[1] - t[2] = x[2] - t[3] = x[3] - - p256OrdSqr(x, x, 16) - p256OrdMul(x, x, t) // ffffffff - t[0] = x[0] - t[1] = x[1] - t[2] = x[2] - t[3] = x[3] - - p256OrdSqr(x, x, 64) // ffffffff0000000000000000 - p256OrdMul(x, x, t) // ffffffff00000000ffffffff - p256OrdSqr(x, x, 32) // ffffffff00000000ffffffff00000000 - p256OrdMul(x, x, t) // ffffffff00000000ffffffffffffffff - - // Remaining 32 windows - expLo := [32]byte{0xb, 0xc, 0xe, 0x6, 0xf, 0xa, 0xa, 0xd, 0xa, 0x7, 0x1, 0x7, 0x9, 0xe, 0x8, 0x4, 0xf, 0x3, 0xb, 0x9, 0xc, 0xa, 0xc, 0x2, 0xf, 0xc, 0x6, 0x3, 0x2, 0x5, 0x4, 0xf} - for i := 0; i < 32; i++ { - p256OrdSqr(x, x, 4) - p256OrdMul(x, x, table[4*(expLo[i]-1):]) + for i, s := range sqrs { + p256OrdSqr(x, x, int(s)) + p256OrdMul(x, x, muls[i]) } // Multiplying by one in the Montgomery domain converts a Montgomery @@ -310,7 +315,7 @@ func (p *p256Point) p256PointToAffine() (x, y *big.Int) { zInv := make([]uint64, 4) zInvSq := make([]uint64, 4) p256Inverse(zInv, p.xyz[8:12]) - p256Sqr(zInvSq, zInv) + p256Sqr(zInvSq, zInv, 1) p256Mul(zInv, zInv, zInvSq) p256Mul(zInvSq, p.xyz[0:4], zInvSq) @@ -347,71 +352,43 @@ func p256Inverse(out, in []uint64) { p16 := stack[4*3 : 4*3+4] p32 := stack[4*4 : 4*4+4] - p256Sqr(out, in) + p256Sqr(out, in, 1) p256Mul(p2, out, in) // 3*p - p256Sqr(out, p2) - p256Sqr(out, out) + p256Sqr(out, p2, 2) p256Mul(p4, out, p2) // f*p - p256Sqr(out, p4) - p256Sqr(out, out) - p256Sqr(out, out) - p256Sqr(out, out) + p256Sqr(out, p4, 4) p256Mul(p8, out, p4) // ff*p - p256Sqr(out, p8) - - for i := 0; i < 7; i++ { - p256Sqr(out, out) - } + p256Sqr(out, p8, 8) p256Mul(p16, out, p8) // ffff*p - p256Sqr(out, p16) - for i := 0; i < 15; i++ { - p256Sqr(out, out) - } + p256Sqr(out, p16, 16) p256Mul(p32, out, p16) // ffffffff*p - p256Sqr(out, p32) - - for i := 0; i < 31; i++ { - p256Sqr(out, out) - } + p256Sqr(out, p32, 32) p256Mul(out, out, in) - for i := 0; i < 32*4; i++ { - p256Sqr(out, out) - } + p256Sqr(out, out, 128) p256Mul(out, out, p32) - for i := 0; i < 32; i++ { - p256Sqr(out, out) - } + p256Sqr(out, out, 32) p256Mul(out, out, p32) - for i := 0; i < 16; i++ { - p256Sqr(out, out) - } + p256Sqr(out, out, 16) p256Mul(out, out, p16) - for i := 0; i < 8; i++ { - p256Sqr(out, out) - } + p256Sqr(out, out, 8) p256Mul(out, out, p8) - p256Sqr(out, out) - p256Sqr(out, out) - p256Sqr(out, out) - p256Sqr(out, out) + p256Sqr(out, out, 4) p256Mul(out, out, p4) - p256Sqr(out, out) - p256Sqr(out, out) + p256Sqr(out, out, 2) p256Mul(out, out, p2) - p256Sqr(out, out) - p256Sqr(out, out) + p256Sqr(out, out, 2) p256Mul(out, out, in) } @@ -427,16 +404,16 @@ func boothW5(in uint) (int, int) { return int(d), int(s & 1) } -func boothW7(in uint) (int, int) { - var s uint = ^((in >> 7) - 1) - var d uint = (1 << 8) - in - 1 +func boothW6(in uint) (int, int) { + var s uint = ^((in >> 6) - 1) + var d uint = (1 << 7) - in - 1 d = (d & s) | (in & (^s)) d = (d >> 1) + (d & 1) return int(d), int(s & 1) } func initTable() { - p256Precomputed = new([37][64 * 8]uint64) + p256Precomputed = new([43][32 * 8]uint64) basePoint := []uint64{ 0x79e730d418a9143c, 0x75ba95fc5fedb601, 0x79fb732b77622510, 0x18905f76a53755c6, @@ -449,19 +426,19 @@ func initTable() { zInv := make([]uint64, 4) zInvSq := make([]uint64, 4) - for j := 0; j < 64; j++ { + for j := 0; j < 32; j++ { copy(t1, t2) - for i := 0; i < 37; i++ { - // The window size is 7 so we need to double 7 times. + 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 < 7; k++ { + 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) + p256Sqr(zInvSq, zInv, 1) p256Mul(zInv, zInv, zInvSq) p256Mul(t1[:4], t1[:4], zInvSq) @@ -482,8 +459,8 @@ func initTable() { func (p *p256Point) p256BaseMult(scalar []uint64) { precomputeOnce.Do(initTable) - wvalue := (scalar[0] << 1) & 0xff - sel, sign := boothW7(uint(wvalue)) + wvalue := (scalar[0] << 1) & 0x7f + sel, sign := boothW6(uint(wvalue)) p256SelectBase(p.xyz[0:8], p256Precomputed[0][0:], sel) p256NegCond(p.xyz[4:8], sign) @@ -500,17 +477,17 @@ func (p *p256Point) p256BaseMult(scalar []uint64) { t0.xyz[10] = 0xffffffffffffffff t0.xyz[11] = 0x00000000fffffffe - index := uint(6) + index := uint(5) zero := sel - for i := 1; i < 37; i++ { + for i := 1; i < 43; i++ { if index < 192 { - wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0xff + wvalue = ((scalar[index/64] >> (index % 64)) + (scalar[index/64+1] << (64 - (index % 64)))) & 0x7f } else { - wvalue = (scalar[index/64] >> (index % 64)) & 0xff + wvalue = (scalar[index/64] >> (index % 64)) & 0x7f } - index += 7 - sel, sign = boothW7(uint(wvalue)) + index += 6 + sel, sign = boothW6(uint(wvalue)) p256SelectBase(t0.xyz[0:8], p256Precomputed[i][0:], sel) p256PointAddAffineAsm(p.xyz[0:12], p.xyz[0:12], t0.xyz[0:8], sign, sel, zero) zero |= sel diff --git a/libgo/go/crypto/elliptic/p256_generic.go b/libgo/go/crypto/elliptic/p256_generic.go index 49445c3999f..48954a2e9c9 100644 --- a/libgo/go/crypto/elliptic/p256_generic.go +++ b/libgo/go/crypto/elliptic/p256_generic.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. -// -build !amd64,!s390x +// -build !amd64,!s390x,!arm64 package elliptic diff --git a/libgo/go/crypto/hmac/hmac.go b/libgo/go/crypto/hmac/hmac.go index 3c8e727bc8c..c8c0617c47f 100644 --- a/libgo/go/crypto/hmac/hmac.go +++ b/libgo/go/crypto/hmac/hmac.go @@ -27,7 +27,7 @@ import ( ) // FIPS 198-1: -// http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf +// https://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf // key is zero padded to the block size of the hash function // ipad = 0x36 byte repeated for key length diff --git a/libgo/go/crypto/hmac/hmac_test.go b/libgo/go/crypto/hmac/hmac_test.go index aac9aa96a8e..eea345edb63 100644 --- a/libgo/go/crypto/hmac/hmac_test.go +++ b/libgo/go/crypto/hmac/hmac_test.go @@ -25,7 +25,7 @@ type hmacTest struct { var hmacTests = []hmacTest{ // Tests from US FIPS 198 - // http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf + // https://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf { sha1.New, []byte{ @@ -205,7 +205,7 @@ var hmacTests = []hmacTest{ sha256.BlockSize, }, - // Tests from http://csrc.nist.gov/groups/ST/toolkit/examples.html + // Tests from https://csrc.nist.gov/groups/ST/toolkit/examples.html // (truncated tag tests are left out) { sha1.New, diff --git a/libgo/go/crypto/internal/cipherhw/cipherhw_amd64.go b/libgo/go/crypto/internal/cipherhw/cipherhw_amd64.go deleted file mode 100644 index be0d490a221..00000000000 --- a/libgo/go/crypto/internal/cipherhw/cipherhw_amd64.go +++ /dev/null @@ -1,16 +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. - -// +build amd64,!gccgo,!appengine - -package cipherhw - -// defined in asm_amd64.s -func hasAESNI() bool - -// AESGCMSupport returns true if the Go standard library supports AES-GCM in -// hardware. -func AESGCMSupport() bool { - return hasAESNI() -} diff --git a/libgo/go/crypto/internal/cipherhw/cipherhw_s390x.go b/libgo/go/crypto/internal/cipherhw/cipherhw_s390x.go deleted file mode 100644 index 9cd76795985..00000000000 --- a/libgo/go/crypto/internal/cipherhw/cipherhw_s390x.go +++ /dev/null @@ -1,18 +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. - -// +build s390x,!gccgo,!appengine - -package cipherhw - -// hasHWSupport reports whether the AES-128, AES-192 and AES-256 cipher message -// (KM) function codes are supported. Note that this function is expensive. -// defined in asm_s390x.s -func hasHWSupport() bool - -var hwSupport = hasHWSupport() - -func AESGCMSupport() bool { - return hwSupport -} diff --git a/libgo/go/crypto/internal/cipherhw/doc.go b/libgo/go/crypto/internal/cipherhw/doc.go deleted file mode 100644 index a75fcf64962..00000000000 --- a/libgo/go/crypto/internal/cipherhw/doc.go +++ /dev/null @@ -1,7 +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 cipherhw exposes common functions for detecting whether hardware -// support for certain ciphers and authenticators is present. -package cipherhw diff --git a/libgo/go/crypto/internal/cipherhw/generic.go b/libgo/go/crypto/internal/cipherhw/generic.go deleted file mode 100644 index 64d90d3b41e..00000000000 --- a/libgo/go/crypto/internal/cipherhw/generic.go +++ /dev/null @@ -1,11 +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. - -// +build !amd64,!s390x gccgo appengine - -package cipherhw - -func AESGCMSupport() bool { - return false -} diff --git a/libgo/go/crypto/internal/randutil/randutil.go b/libgo/go/crypto/internal/randutil/randutil.go new file mode 100644 index 00000000000..84b1295a877 --- /dev/null +++ b/libgo/go/crypto/internal/randutil/randutil.go @@ -0,0 +1,38 @@ +// 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 randutil contains internal randomness utilities for various +// crypto packages. +package randutil + +import ( + "io" + "sync" +) + +var ( + closedChanOnce sync.Once + closedChan chan struct{} +) + +// MaybeReadByte reads a single byte from r with ~50% probability. This is used +// to ensure that callers do not depend on non-guaranteed behaviour, e.g. +// assuming that rsa.GenerateKey is deterministic w.r.t. a given random stream. +// +// This does not affect tests that pass a stream of fixed bytes as the random +// source (e.g. a zeroReader). +func MaybeReadByte(r io.Reader) { + closedChanOnce.Do(func() { + closedChan = make(chan struct{}) + close(closedChan) + }) + + select { + case <-closedChan: + return + case <-closedChan: + var buf [1]byte + r.Read(buf[:]) + } +} diff --git a/libgo/go/crypto/internal/subtle/aliasing.go b/libgo/go/crypto/internal/subtle/aliasing.go new file mode 100644 index 00000000000..812ce3c6552 --- /dev/null +++ b/libgo/go/crypto/internal/subtle/aliasing.go @@ -0,0 +1,34 @@ +// 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 !appengine + +// Package subtle implements functions that are often useful in cryptographic +// code but require careful thought to use correctly. +// +// This is a mirror of golang.org/x/crypto/internal/subtle. +package subtle // import "crypto/internal/subtle" + +import "unsafe" + +// 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 && + uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && + uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) +} + +// 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/crypto/internal/subtle/aliasing_appengine.go b/libgo/go/crypto/internal/subtle/aliasing_appengine.go new file mode 100644 index 00000000000..844f901d18e --- /dev/null +++ b/libgo/go/crypto/internal/subtle/aliasing_appengine.go @@ -0,0 +1,37 @@ +// 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 appengine + +// Package subtle implements functions that are often useful in cryptographic +// code but require careful thought to use correctly. +// +// This is a mirror of golang.org/x/crypto/internal/subtle. +package subtle // import "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/crypto/internal/subtle/aliasing_test.go b/libgo/go/crypto/internal/subtle/aliasing_test.go new file mode 100644 index 00000000000..f1e72384812 --- /dev/null +++ b/libgo/go/crypto/internal/subtle/aliasing_test.go @@ -0,0 +1,50 @@ +// 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 subtle_test + +import ( + "testing" + + "crypto/internal/subtle" +) + +var a, b [100]byte + +var aliasingTests = []struct { + x, y []byte + anyOverlap, inexactOverlap bool +}{ + {a[:], b[:], false, false}, + {a[:], b[:0], false, false}, + {a[:], b[:50], false, false}, + {a[40:50], a[50:60], false, false}, + {a[40:50], a[60:70], false, false}, + {a[:51], a[50:], true, true}, + {a[:], a[:], true, false}, + {a[:50], a[:60], true, false}, + {a[:], nil, false, false}, + {nil, nil, false, false}, + {a[:], a[:0], false, false}, + {a[:10], a[:10:20], true, false}, + {a[:10], a[5:10:20], true, true}, +} + +func testAliasing(t *testing.T, i int, x, y []byte, anyOverlap, inexactOverlap bool) { + any := subtle.AnyOverlap(x, y) + if any != anyOverlap { + t.Errorf("%d: wrong AnyOverlap result, expected %v, got %v", i, anyOverlap, any) + } + inexact := subtle.InexactOverlap(x, y) + if inexact != inexactOverlap { + t.Errorf("%d: wrong InexactOverlap result, expected %v, got %v", i, inexactOverlap, any) + } +} + +func TestAliasing(t *testing.T) { + for i, tt := range aliasingTests { + testAliasing(t, i, tt.x, tt.y, tt.anyOverlap, tt.inexactOverlap) + testAliasing(t, i, tt.y, tt.x, tt.anyOverlap, tt.inexactOverlap) + } +} diff --git a/libgo/go/crypto/md5/gen.go b/libgo/go/crypto/md5/gen.go index 178fad18285..a815dc29f6a 100644 --- a/libgo/go/crypto/md5/gen.go +++ b/libgo/go/crypto/md5/gen.go @@ -179,8 +179,7 @@ var program = `// 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. -// DO NOT EDIT. -// Generate with: go run gen.go{{if .Full}} -full{{end}} -output md5block.go +// Code generated by go run gen.go{{if .Full}} -full{{end}} -output md5block.go; DO NOT EDIT. package md5 diff --git a/libgo/go/crypto/md5/md5.go b/libgo/go/crypto/md5/md5.go index 7aeee603f70..88d914d22ce 100644 --- a/libgo/go/crypto/md5/md5.go +++ b/libgo/go/crypto/md5/md5.go @@ -64,7 +64,7 @@ func (d *digest) MarshalBinary() ([]byte, error) { b = appendUint32(b, d.s[2]) b = appendUint32(b, d.s[3]) b = append(b, d.x[:d.nx]...) - b = b[:len(b)+len(d.x)-int(d.nx)] // already zero + b = b[:len(b)+len(d.x)-d.nx] // already zero b = appendUint64(b, d.len) return b, nil } @@ -160,10 +160,10 @@ func (d *digest) Write(p []byte) (nn int, err error) { return } -func (d0 *digest) Sum(in []byte) []byte { - // Make a copy of d0 so that caller can keep writing and summing. - d := *d0 - hash := d.checkSum() +func (d *digest) Sum(in []byte) []byte { + // Make a copy of d so that caller can keep writing and summing. + d0 := *d + hash := d0.checkSum() return append(in, hash[:]...) } diff --git a/libgo/go/crypto/md5/md5block.go b/libgo/go/crypto/md5/md5block.go index 64e1e7c1efd..8ac32ffeb78 100644 --- a/libgo/go/crypto/md5/md5block.go +++ b/libgo/go/crypto/md5/md5block.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. -// DO NOT EDIT. -// Generate with: go run gen.go -full -output md5block.go +// Code generated by go run gen.go -full -output md5block.go; DO NOT EDIT. package md5 diff --git a/libgo/go/crypto/md5/md5block_decl.go b/libgo/go/crypto/md5/md5block_decl.go index 4de38cf822a..5f9d7aba487 100644 --- a/libgo/go/crypto/md5/md5block_decl.go +++ b/libgo/go/crypto/md5/md5block_decl.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build ignore -// -build amd64 amd64p32 386 arm ppc64le s390x +// -build amd64 amd64p32 386 arm ppc64le s390x arm64 package md5 diff --git a/libgo/go/crypto/md5/md5block_generic.go b/libgo/go/crypto/md5/md5block_generic.go index c23d02b8d40..c580bc6d094 100644 --- a/libgo/go/crypto/md5/md5block_generic.go +++ b/libgo/go/crypto/md5/md5block_generic.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. -// -build !amd64,!amd64p32,!386,!arm,!ppc64le,!s390x +// -build !amd64,!amd64p32,!386,!arm,!ppc64le,!s390x,!arm64 package md5 diff --git a/libgo/go/crypto/rand/rand.go b/libgo/go/crypto/rand/rand.go index 6f7523d9d73..b8df8a37117 100644 --- a/libgo/go/crypto/rand/rand.go +++ b/libgo/go/crypto/rand/rand.go @@ -3,18 +3,19 @@ // license that can be found in the LICENSE file. // Package rand implements a cryptographically secure -// pseudorandom number generator. +// random number generator. package rand import "io" // Reader is a global, shared instance of a cryptographically -// strong pseudo-random generator. +// secure random number generator. // // On Linux, Reader uses getrandom(2) if available, /dev/urandom otherwise. // On OpenBSD, Reader uses getentropy(2). // On other Unix-like systems, Reader reads from /dev/urandom. // On Windows systems, Reader uses the CryptGenRandom API. +// On Wasm, Reader uses the Web Crypto API. var Reader io.Reader // Read is a helper function that calls Reader.Read using io.ReadFull. diff --git a/libgo/go/crypto/rand/rand_js.go b/libgo/go/crypto/rand/rand_js.go new file mode 100644 index 00000000000..bb213963fd4 --- /dev/null +++ b/libgo/go/crypto/rand/rand_js.go @@ -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. + +// +build js,wasm + +package rand + +import "syscall/js" + +func init() { + Reader = &reader{} +} + +var jsCrypto = js.Global().Get("crypto") + +// reader implements a pseudorandom generator +// using JavaScript crypto.getRandomValues method. +// See https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues. +type reader struct{} + +func (r *reader) Read(b []byte) (int, error) { + a := js.TypedArrayOf(b) + jsCrypto.Call("getRandomValues", a) + a.Release() + return len(b), nil +} diff --git a/libgo/go/crypto/rc4/rc4.go b/libgo/go/crypto/rc4/rc4.go index 8274325c81a..c445bb078f2 100644 --- a/libgo/go/crypto/rc4/rc4.go +++ b/libgo/go/crypto/rc4/rc4.go @@ -9,7 +9,10 @@ // applications. package rc4 -import "strconv" +import ( + "crypto/internal/subtle" + "strconv" +) // A Cipher is an instance of RC4 using a particular key. type Cipher struct { @@ -57,12 +60,22 @@ func (c *Cipher) Reset() { // This is the pure Go version. rc4_{amd64,386,arm}* contain assembly // implementations. This is here for tests and to prevent bitrot. func (c *Cipher) xorKeyStreamGeneric(dst, src []byte) { + if len(src) == 0 { + return + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/rc4: invalid buffer overlap") + } i, j := c.i, c.j + _ = dst[len(src)-1] + dst = dst[:len(src)] // eliminate bounds check from loop for k, v := range src { i += 1 - j += uint8(c.s[i]) - c.s[i], c.s[j] = c.s[j], c.s[i] - dst[k] = v ^ uint8(c.s[uint8(c.s[i]+c.s[j])]) + x := c.s[i] + j += uint8(x) + y := c.s[j] + c.s[i], c.s[j] = y, x + dst[k] = v ^ uint8(c.s[uint8(x+y)]) } c.i, c.j = i, j } diff --git a/libgo/go/crypto/rc4/rc4_asm.go b/libgo/go/crypto/rc4/rc4_asm.go index aea1939597a..ce2162df603 100644 --- a/libgo/go/crypto/rc4/rc4_asm.go +++ b/libgo/go/crypto/rc4/rc4_asm.go @@ -8,6 +8,8 @@ package rc4 +import "crypto/internal/subtle" + func xorKeyStream(dst, src *byte, n int, state *[256]uint32, i, j *uint8) // XORKeyStream sets dst to the result of XORing src with the key stream. @@ -16,7 +18,11 @@ func (c *Cipher) XORKeyStream(dst, src []byte) { if len(src) == 0 { return } - // Assert len(dst) >= len(src) - _ = dst[len(src)-1] + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + if subtle.InexactOverlap(dst[:len(src)], src) { + panic("crypto/cipher: invalid buffer overlap") + } xorKeyStream(&dst[0], &src[0], len(src), &c.s, &c.i, &c.j) } diff --git a/libgo/go/crypto/rc4/rc4_test.go b/libgo/go/crypto/rc4/rc4_test.go index af798824632..1fc08b85934 100644 --- a/libgo/go/crypto/rc4/rc4_test.go +++ b/libgo/go/crypto/rc4/rc4_test.go @@ -16,7 +16,7 @@ type rc4Test struct { var golden = []rc4Test{ // Test vectors from the original cypherpunk posting of ARC4: - // http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0?pli=1 + // https://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0?pli=1 { []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, []byte{0x74, 0x94, 0xc2, 0xe7, 0x10, 0x4b, 0x08, 0x79}, @@ -30,7 +30,7 @@ var golden = []rc4Test{ []byte{0xd6, 0xa1, 0x41, 0xa7, 0xec, 0x3c, 0x38, 0xdf, 0xbd, 0x61}, }, - // Test vectors from the Wikipedia page: http://en.wikipedia.org/wiki/RC4 + // Test vectors from the Wikipedia page: https://en.wikipedia.org/wiki/RC4 { []byte{0x4b, 0x65, 0x79}, []byte{0xeb, 0x9f, 0x77, 0x81, 0xb7, 0x34, 0xca, 0x72, 0xa7, 0x19}, diff --git a/libgo/go/crypto/rsa/pkcs1v15.go b/libgo/go/crypto/rsa/pkcs1v15.go index 3517a8c776c..37790acb986 100644 --- a/libgo/go/crypto/rsa/pkcs1v15.go +++ b/libgo/go/crypto/rsa/pkcs1v15.go @@ -10,6 +10,8 @@ import ( "errors" "io" "math/big" + + "crypto/internal/randutil" ) // This file implements encryption and decryption using PKCS#1 v1.5 padding. @@ -35,10 +37,12 @@ type PKCS1v15DecryptOptions struct { // WARNING: use of this function to encrypt plaintexts other than // session keys is dangerous. Use RSA OAEP in new protocols. func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) { + randutil.MaybeReadByte(rand) + if err := checkPub(pub); err != nil { return nil, err } - k := (pub.N.BitLen() + 7) / 8 + k := pub.Size() if len(msg) > k-11 { return nil, ErrMessageTooLong } @@ -106,7 +110,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by if err := checkPub(&priv.PublicKey); err != nil { return err } - k := (priv.N.BitLen() + 7) / 8 + k := priv.Size() if k-(len(key)+3+8) < 0 { return ErrDecryption } @@ -134,7 +138,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by // in order to maintain constant memory access patterns. If the plaintext was // valid then index contains the index of the original message in em. func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) { - k := (priv.N.BitLen() + 7) / 8 + k := priv.Size() if k < 11 { err = ErrDecryption return @@ -232,7 +236,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b } tLen := len(prefix) + hashLen - k := (priv.N.BitLen() + 7) / 8 + k := priv.Size() if k < tLen+11 { return nil, ErrMessageTooLong } @@ -268,7 +272,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) } tLen := len(prefix) + hashLen - k := (pub.N.BitLen() + 7) / 8 + k := pub.Size() if k < tLen+11 { return ErrVerification } diff --git a/libgo/go/crypto/rsa/pss.go b/libgo/go/crypto/rsa/pss.go index 75558a92cf1..3ff0c2f4d00 100644 --- a/libgo/go/crypto/rsa/pss.go +++ b/libgo/go/crypto/rsa/pss.go @@ -36,7 +36,7 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop. if emLen < hLen+sLen+2 { - return nil, errors.New("crypto/rsa: encoding error") + return nil, errors.New("crypto/rsa: key size too small for PSS signature") } em := make([]byte, emLen) diff --git a/libgo/go/crypto/rsa/rsa.go b/libgo/go/crypto/rsa/rsa.go index 0faca43e430..ad32d3e3add 100644 --- a/libgo/go/crypto/rsa/rsa.go +++ b/libgo/go/crypto/rsa/rsa.go @@ -31,6 +31,8 @@ import ( "io" "math" "math/big" + + "crypto/internal/randutil" ) var bigZero = big.NewInt(0) @@ -42,6 +44,12 @@ type PublicKey struct { E int // public exponent } +// Size returns the modulus size in bytes. Raw signatures and ciphertexts +// for or by this public key will have the same size. +func (pub *PublicKey) Size() int { + return (pub.N.BitLen() + 7) / 8 +} + // OAEPOptions is an interface for passing options to OAEP decryption using the // crypto.Decrypter interface. type OAEPOptions struct { @@ -62,7 +70,7 @@ var ( // We require pub.E to fit into a 32-bit integer so that we // do not have different behavior depending on whether // int is 32 or 64 bits. See also -// http://www.imperialviolet.org/2012/03/16/rsae.html. +// https://www.imperialviolet.org/2012/03/16/rsae.html. func checkPub(pub *PublicKey) error { if pub.N == nil { return errPublicModulus @@ -212,6 +220,8 @@ func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) { // [1] US patent 4405829 (1972, expired) // [2] http://www.cacr.math.uwaterloo.ca/techreports/2006/cacr2006-16.pdf func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) { + randutil.MaybeReadByte(random) + priv := new(PrivateKey) priv.E = 65537 @@ -286,18 +296,13 @@ NextSetOfPrimes: continue NextSetOfPrimes } - g := new(big.Int) priv.D = new(big.Int) e := big.NewInt(int64(priv.E)) - g.GCD(priv.D, nil, e, totient) + ok := priv.D.ModInverse(e, totient) - if g.Cmp(bigOne) == 0 { - if priv.D.Sign() < 0 { - priv.D.Add(priv.D, totient) - } + if ok != nil { priv.Primes = primes priv.N = n - break } } @@ -373,7 +378,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l return nil, err } hash.Reset() - k := (pub.N.BitLen() + 7) / 8 + k := pub.Size() if len(msg) > k-2*hash.Size()-2 { return nil, ErrMessageTooLong } @@ -421,29 +426,6 @@ var ErrDecryption = errors.New("crypto/rsa: decryption error") // It is deliberately vague to avoid adaptive attacks. var ErrVerification = errors.New("crypto/rsa: verification error") -// modInverse returns ia, the inverse of a in the multiplicative group of prime -// order n. It requires that a be a member of the group (i.e. less than n). -func modInverse(a, n *big.Int) (ia *big.Int, ok bool) { - g := new(big.Int) - x := new(big.Int) - g.GCD(x, nil, a, n) - if g.Cmp(bigOne) != 0 { - // In this case, a and n aren't coprime and we cannot calculate - // the inverse. This happens because the values of n are nearly - // prime (being the product of two primes) rather than truly - // prime. - return - } - - if x.Cmp(bigOne) < 0 { - // 0 is not the multiplicative inverse of any element so, if x - // < 1, then x is negative. - x.Add(x, n) - } - - return x, true -} - // Precompute performs some calculations that speed up private key operations // in the future. func (priv *PrivateKey) Precompute() { @@ -489,13 +471,15 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er var ir *big.Int if random != nil { + randutil.MaybeReadByte(random) + // Blinding enabled. Blinding involves multiplying c by r^e. // Then the decryption operation performs (m^e * r^e)^d mod n // which equals mr mod n. The factor of r can then be removed // by multiplying by the multiplicative inverse of r. var r *big.Int - + ir = new(big.Int) for { r, err = rand.Int(random, priv.N) if err != nil { @@ -504,9 +488,8 @@ func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err er if r.Cmp(bigZero) == 0 { r = bigOne } - var ok bool - ir, ok = modInverse(r, priv.N) - if ok { + ok := ir.ModInverse(r, priv.N) + if ok != nil { break } } @@ -587,7 +570,7 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext if err := checkPub(&priv.PublicKey); err != nil { return nil, err } - k := (priv.N.BitLen() + 7) / 8 + k := priv.Size() if len(ciphertext) > k || k < hash.Size()*2+2 { return nil, ErrDecryption diff --git a/libgo/go/crypto/sha1/sha1.go b/libgo/go/crypto/sha1/sha1.go index ae4896fc328..db70b7d09aa 100644 --- a/libgo/go/crypto/sha1/sha1.go +++ b/libgo/go/crypto/sha1/sha1.go @@ -150,10 +150,10 @@ func (d *digest) Write(p []byte) (nn int, err error) { return } -func (d0 *digest) Sum(in []byte) []byte { - // Make a copy of d0 so that caller can keep writing and summing. - d := *d0 - hash := d.checkSum() +func (d *digest) Sum(in []byte) []byte { + // Make a copy of d so that caller can keep writing and summing. + d0 := *d + hash := d0.checkSum() return append(in, hash[:]...) } @@ -189,9 +189,9 @@ func (d *digest) checkSum() [Size]byte { } // ConstantTimeSum computes the same result of Sum() but in constant time -func (d0 *digest) ConstantTimeSum(in []byte) []byte { - d := *d0 - hash := d.constSum() +func (d *digest) ConstantTimeSum(in []byte) []byte { + d0 := *d + hash := d0.constSum() return append(in, hash[:]...) } diff --git a/libgo/go/crypto/sha1/sha1block_s390x.go b/libgo/go/crypto/sha1/sha1block_s390x.go index 55a23599a97..64c4018593f 100644 --- a/libgo/go/crypto/sha1/sha1block_s390x.go +++ b/libgo/go/crypto/sha1/sha1block_s390x.go @@ -6,9 +6,6 @@ package sha1 -// featureCheck reports whether the CPU supports the -// SHA-1 compute intermediate message digest (KIMD) -// function code. -func featureCheck() bool +import "internal/cpu" -var useAsm = featureCheck() +var useAsm = cpu.S390X.HasSHA1 diff --git a/libgo/go/crypto/sha256/sha256.go b/libgo/go/crypto/sha256/sha256.go index b8ddaf43bbb..1389de27277 100644 --- a/libgo/go/crypto/sha256/sha256.go +++ b/libgo/go/crypto/sha256/sha256.go @@ -104,27 +104,35 @@ func (d *digest) UnmarshalBinary(b []byte) error { return nil } +func putUint32(x []byte, s uint32) { + _ = x[3] + x[0] = byte(s >> 24) + x[1] = byte(s >> 16) + x[2] = byte(s >> 8) + x[3] = byte(s) +} + +func putUint64(x []byte, s uint64) { + _ = x[7] + x[0] = byte(s >> 56) + x[1] = byte(s >> 48) + x[2] = byte(s >> 40) + x[3] = byte(s >> 32) + x[4] = byte(s >> 24) + x[5] = byte(s >> 16) + x[6] = byte(s >> 8) + x[7] = byte(s) +} + func appendUint64(b []byte, x uint64) []byte { - a := [8]byte{ - byte(x >> 56), - byte(x >> 48), - byte(x >> 40), - byte(x >> 32), - byte(x >> 24), - byte(x >> 16), - byte(x >> 8), - byte(x), - } + var a [8]byte + putUint64(a[:], x) return append(b, a[:]...) } func appendUint32(b []byte, x uint32) []byte { - a := [4]byte{ - byte(x >> 24), - byte(x >> 16), - byte(x >> 8), - byte(x), - } + var a [4]byte + putUint32(a[:], x) return append(b, a[:]...) } @@ -215,11 +223,11 @@ func (d *digest) Write(p []byte) (nn int, err error) { return } -func (d0 *digest) Sum(in []byte) []byte { - // Make a copy of d0 so that caller can keep writing and summing. - d := *d0 - hash := d.checkSum() - if d.is224 { +func (d *digest) Sum(in []byte) []byte { + // Make a copy of d so that caller can keep writing and summing. + d0 := *d + hash := d0.checkSum() + if d0.is224 { return append(in, hash[:Size224]...) } return append(in, hash[:]...) @@ -238,26 +246,24 @@ func (d *digest) checkSum() [Size]byte { // Length in bits. len <<= 3 - for i := uint(0); i < 8; i++ { - tmp[i] = byte(len >> (56 - 8*i)) - } + putUint64(tmp[:], len) d.Write(tmp[0:8]) if d.nx != 0 { panic("d.nx != 0") } - h := d.h[:] - if d.is224 { - h = d.h[:7] - } - var digest [Size]byte - for i, s := range h { - digest[i*4] = byte(s >> 24) - digest[i*4+1] = byte(s >> 16) - digest[i*4+2] = byte(s >> 8) - digest[i*4+3] = byte(s) + + putUint32(digest[0:], d.h[0]) + putUint32(digest[4:], d.h[1]) + putUint32(digest[8:], d.h[2]) + putUint32(digest[12:], d.h[3]) + putUint32(digest[16:], d.h[4]) + putUint32(digest[20:], d.h[5]) + putUint32(digest[24:], d.h[6]) + if !d.is224 { + putUint32(digest[28:], d.h[7]) } return digest diff --git a/libgo/go/crypto/sha256/sha256block_s390x.go b/libgo/go/crypto/sha256/sha256block_s390x.go index 8e5f69d4e5b..4de1c83eaa1 100644 --- a/libgo/go/crypto/sha256/sha256block_s390x.go +++ b/libgo/go/crypto/sha256/sha256block_s390x.go @@ -6,9 +6,6 @@ package sha256 -// featureCheck reports whether the CPU supports the -// SHA256 compute intermediate message digest (KIMD) -// function code. -func featureCheck() bool +import "internal/cpu" -var useAsm = featureCheck() +var useAsm = cpu.S390X.HasSHA256 diff --git a/libgo/go/crypto/sha512/sha512.go b/libgo/go/crypto/sha512/sha512.go index b1999516ebd..24fde7dce70 100644 --- a/libgo/go/crypto/sha512/sha512.go +++ b/libgo/go/crypto/sha512/sha512.go @@ -195,17 +195,21 @@ func (d *digest) UnmarshalBinary(b []byte) error { return nil } +func putUint64(x []byte, s uint64) { + _ = x[7] + x[0] = byte(s >> 56) + x[1] = byte(s >> 48) + x[2] = byte(s >> 40) + x[3] = byte(s >> 32) + x[4] = byte(s >> 24) + x[5] = byte(s >> 16) + x[6] = byte(s >> 8) + x[7] = byte(s) +} + func appendUint64(b []byte, x uint64) []byte { - a := [8]byte{ - byte(x >> 56), - byte(x >> 48), - byte(x >> 40), - byte(x >> 32), - byte(x >> 24), - byte(x >> 16), - byte(x >> 8), - byte(x), - } + var a [8]byte + putUint64(a[:], x) return append(b, a[:]...) } @@ -282,12 +286,12 @@ func (d *digest) Write(p []byte) (nn int, err error) { return } -func (d0 *digest) Sum(in []byte) []byte { - // Make a copy of d0 so that caller can keep writing and summing. - d := new(digest) - *d = *d0 - hash := d.checkSum() - switch d.function { +func (d *digest) Sum(in []byte) []byte { + // Make a copy of d so that caller can keep writing and summing. + d0 := new(digest) + *d0 = *d + hash := d0.checkSum() + switch d0.function { case crypto.SHA384: return append(in, hash[:Size384]...) case crypto.SHA512_224: @@ -312,30 +316,24 @@ func (d *digest) checkSum() [Size]byte { // Length in bits. len <<= 3 - for i := uint(0); i < 16; i++ { - tmp[i] = byte(len >> (120 - 8*i)) - } + putUint64(tmp[0:], 0) // upper 64 bits are always zero, because len variable has type uint64 + putUint64(tmp[8:], len) d.Write(tmp[0:16]) if d.nx != 0 { panic("d.nx != 0") } - h := d.h[:] - if d.function == crypto.SHA384 { - h = d.h[:6] - } - var digest [Size]byte - for i, s := range h { - digest[i*8] = byte(s >> 56) - digest[i*8+1] = byte(s >> 48) - digest[i*8+2] = byte(s >> 40) - digest[i*8+3] = byte(s >> 32) - digest[i*8+4] = byte(s >> 24) - digest[i*8+5] = byte(s >> 16) - digest[i*8+6] = byte(s >> 8) - digest[i*8+7] = byte(s) + putUint64(digest[0:], d.h[0]) + putUint64(digest[8:], d.h[1]) + putUint64(digest[16:], d.h[2]) + putUint64(digest[24:], d.h[3]) + putUint64(digest[32:], d.h[4]) + putUint64(digest[40:], d.h[5]) + if d.function != crypto.SHA384 { + putUint64(digest[48:], d.h[6]) + putUint64(digest[56:], d.h[7]) } return digest diff --git a/libgo/go/crypto/sha512/sha512block_s390x.go b/libgo/go/crypto/sha512/sha512block_s390x.go index 26896fcec4c..f8ab23111dd 100644 --- a/libgo/go/crypto/sha512/sha512block_s390x.go +++ b/libgo/go/crypto/sha512/sha512block_s390x.go @@ -6,9 +6,6 @@ package sha512 -// featureCheck reports whether the CPU supports the -// SHA512 compute intermediate message digest (KIMD) -// function code. -func featureCheck() bool +import "internal/cpu" -var useAsm = featureCheck() +var useAsm = cpu.S390X.HasSHA512 diff --git a/libgo/go/crypto/tls/auth.go b/libgo/go/crypto/tls/auth.go new file mode 100644 index 00000000000..88face4cdee --- /dev/null +++ b/libgo/go/crypto/tls/auth.go @@ -0,0 +1,108 @@ +// 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 tls + +import ( + "crypto" + "crypto/ecdsa" + "crypto/rsa" + "encoding/asn1" + "errors" + "fmt" +) + +// pickSignatureAlgorithm selects a signature algorithm that is compatible with +// the given public key and the list of algorithms from the peer and this side. +// The lists of signature algorithms (peerSigAlgs and ourSigAlgs) are ignored +// for tlsVersion < VersionTLS12. +// +// The returned SignatureScheme codepoint is only meaningful for TLS 1.2, +// previous TLS versions have a fixed hash function. +func pickSignatureAlgorithm(pubkey crypto.PublicKey, peerSigAlgs, ourSigAlgs []SignatureScheme, tlsVersion uint16) (sigAlg SignatureScheme, sigType uint8, hashFunc crypto.Hash, err error) { + if tlsVersion < VersionTLS12 || len(peerSigAlgs) == 0 { + // For TLS 1.1 and before, the signature algorithm could not be + // negotiated and the hash is fixed based on the signature type. + // For TLS 1.2, if the client didn't send signature_algorithms + // extension then we can assume that it supports SHA1. See + // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 + switch pubkey.(type) { + case *rsa.PublicKey: + if tlsVersion < VersionTLS12 { + return 0, signaturePKCS1v15, crypto.MD5SHA1, nil + } else { + return PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1, nil + } + case *ecdsa.PublicKey: + return ECDSAWithSHA1, signatureECDSA, crypto.SHA1, nil + default: + return 0, 0, 0, fmt.Errorf("tls: unsupported public key: %T", pubkey) + } + } + for _, sigAlg := range peerSigAlgs { + if !isSupportedSignatureAlgorithm(sigAlg, ourSigAlgs) { + continue + } + hashAlg, err := lookupTLSHash(sigAlg) + if err != nil { + panic("tls: supported signature algorithm has an unknown hash function") + } + sigType := signatureFromSignatureScheme(sigAlg) + switch pubkey.(type) { + case *rsa.PublicKey: + if sigType == signaturePKCS1v15 || sigType == signatureRSAPSS { + return sigAlg, sigType, hashAlg, nil + } + case *ecdsa.PublicKey: + if sigType == signatureECDSA { + return sigAlg, sigType, hashAlg, nil + } + default: + return 0, 0, 0, fmt.Errorf("tls: unsupported public key: %T", pubkey) + } + } + return 0, 0, 0, errors.New("tls: peer doesn't support any common signature algorithms") +} + +// verifyHandshakeSignature verifies a signature against pre-hashed handshake +// contents. +func verifyHandshakeSignature(sigType uint8, pubkey crypto.PublicKey, hashFunc crypto.Hash, digest, sig []byte) error { + switch sigType { + case signatureECDSA: + pubKey, ok := pubkey.(*ecdsa.PublicKey) + if !ok { + return errors.New("tls: ECDSA signing requires a ECDSA public key") + } + ecdsaSig := new(ecdsaSignature) + if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil { + return err + } + if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { + return errors.New("tls: ECDSA signature contained zero or negative values") + } + if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) { + return errors.New("tls: ECDSA verification failure") + } + case signaturePKCS1v15: + pubKey, ok := pubkey.(*rsa.PublicKey) + if !ok { + return errors.New("tls: RSA signing requires a RSA public key") + } + if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil { + return err + } + case signatureRSAPSS: + pubKey, ok := pubkey.(*rsa.PublicKey) + if !ok { + return errors.New("tls: RSA signing requires a RSA public key") + } + signOpts := &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash} + if err := rsa.VerifyPSS(pubKey, hashFunc, digest, sig, signOpts); err != nil { + return err + } + default: + return errors.New("tls: unknown signature algorithm") + } + return nil +} diff --git a/libgo/go/crypto/tls/auth_test.go b/libgo/go/crypto/tls/auth_test.go new file mode 100644 index 00000000000..3f876b9e1a9 --- /dev/null +++ b/libgo/go/crypto/tls/auth_test.go @@ -0,0 +1,101 @@ +// 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 tls + +import ( + "crypto" + "testing" +) + +func TestSignatureSelection(t *testing.T) { + rsaCert := &testRSAPrivateKey.PublicKey + ecdsaCert := &testECDSAPrivateKey.PublicKey + sigsPKCS1WithSHA := []SignatureScheme{PKCS1WithSHA256, PKCS1WithSHA1} + sigsPSSWithSHA := []SignatureScheme{PSSWithSHA256, PSSWithSHA384} + sigsECDSAWithSHA := []SignatureScheme{ECDSAWithP256AndSHA256, ECDSAWithSHA1} + + tests := []struct { + pubkey crypto.PublicKey + peerSigAlgs []SignatureScheme + ourSigAlgs []SignatureScheme + tlsVersion uint16 + + expectedSigAlg SignatureScheme // or 0 if ignored + expectedSigType uint8 + expectedHash crypto.Hash + }{ + // Hash is fixed for RSA in TLS 1.1 and before. + // https://tools.ietf.org/html/rfc4346#page-44 + {rsaCert, nil, nil, VersionTLS11, 0, signaturePKCS1v15, crypto.MD5SHA1}, + {rsaCert, nil, nil, VersionTLS10, 0, signaturePKCS1v15, crypto.MD5SHA1}, + {rsaCert, nil, nil, VersionSSL30, 0, signaturePKCS1v15, crypto.MD5SHA1}, + + // Before TLS 1.2, there is no signature_algorithms extension + // nor field in CertificateRequest and digitally-signed and thus + // it should be ignored. + {rsaCert, sigsPKCS1WithSHA, nil, VersionTLS11, 0, signaturePKCS1v15, crypto.MD5SHA1}, + {rsaCert, sigsPKCS1WithSHA, sigsPKCS1WithSHA, VersionTLS11, 0, signaturePKCS1v15, crypto.MD5SHA1}, + // Use SHA-1 for TLS 1.0 and 1.1 with ECDSA, see https://tools.ietf.org/html/rfc4492#page-20 + {ecdsaCert, sigsPKCS1WithSHA, sigsPKCS1WithSHA, VersionTLS11, 0, signatureECDSA, crypto.SHA1}, + {ecdsaCert, sigsPKCS1WithSHA, sigsPKCS1WithSHA, VersionTLS10, 0, signatureECDSA, crypto.SHA1}, + + // TLS 1.2 without signature_algorithms extension + // https://tools.ietf.org/html/rfc5246#page-47 + {rsaCert, nil, sigsPKCS1WithSHA, VersionTLS12, PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1}, + {ecdsaCert, nil, sigsPKCS1WithSHA, VersionTLS12, ECDSAWithSHA1, signatureECDSA, crypto.SHA1}, + + {rsaCert, []SignatureScheme{PKCS1WithSHA1}, sigsPKCS1WithSHA, VersionTLS12, PKCS1WithSHA1, signaturePKCS1v15, crypto.SHA1}, + {rsaCert, []SignatureScheme{PKCS1WithSHA256}, sigsPKCS1WithSHA, VersionTLS12, PKCS1WithSHA256, signaturePKCS1v15, crypto.SHA256}, + // "sha_hash" may denote hashes other than SHA-1 + // https://tools.ietf.org/html/draft-ietf-tls-rfc4492bis-17#page-17 + {ecdsaCert, []SignatureScheme{ECDSAWithSHA1}, sigsECDSAWithSHA, VersionTLS12, ECDSAWithSHA1, signatureECDSA, crypto.SHA1}, + {ecdsaCert, []SignatureScheme{ECDSAWithP256AndSHA256}, sigsECDSAWithSHA, VersionTLS12, ECDSAWithP256AndSHA256, signatureECDSA, crypto.SHA256}, + + // RSASSA-PSS is defined in TLS 1.3 for TLS 1.2 + // https://tools.ietf.org/html/draft-ietf-tls-tls13-21#page-45 + {rsaCert, []SignatureScheme{PSSWithSHA256}, sigsPSSWithSHA, VersionTLS12, PSSWithSHA256, signatureRSAPSS, crypto.SHA256}, + } + + for testNo, test := range tests { + sigAlg, sigType, hashFunc, err := pickSignatureAlgorithm(test.pubkey, test.peerSigAlgs, test.ourSigAlgs, test.tlsVersion) + if err != nil { + t.Errorf("test[%d]: unexpected error: %v", testNo, err) + } + if test.expectedSigAlg != 0 && test.expectedSigAlg != sigAlg { + t.Errorf("test[%d]: expected signature scheme %#x, got %#x", testNo, test.expectedSigAlg, sigAlg) + } + if test.expectedSigType != sigType { + t.Errorf("test[%d]: expected signature algorithm %#x, got %#x", testNo, test.expectedSigType, sigType) + } + if test.expectedHash != hashFunc { + t.Errorf("test[%d]: expected hash function %#x, got %#x", testNo, test.expectedHash, hashFunc) + } + } + + badTests := []struct { + pubkey crypto.PublicKey + peerSigAlgs []SignatureScheme + ourSigAlgs []SignatureScheme + tlsVersion uint16 + }{ + {rsaCert, sigsECDSAWithSHA, sigsPKCS1WithSHA, VersionTLS12}, + {ecdsaCert, sigsPKCS1WithSHA, sigsPKCS1WithSHA, VersionTLS12}, + {ecdsaCert, sigsECDSAWithSHA, sigsPKCS1WithSHA, VersionTLS12}, + {rsaCert, []SignatureScheme{0}, sigsPKCS1WithSHA, VersionTLS12}, + + // ECDSA is unspecified for SSL 3.0 in RFC 4492. + // TODO a SSL 3.0 client cannot advertise signature_algorithms, + // but if an application feeds an ECDSA certificate anyway, it + // will be accepted rather than trigger a handshake failure. Ok? + //{ecdsaCert, nil, nil, VersionSSL30}, + } + + for testNo, test := range badTests { + sigAlg, sigType, hashFunc, err := pickSignatureAlgorithm(test.pubkey, test.peerSigAlgs, test.ourSigAlgs, test.tlsVersion) + if err == nil { + t.Errorf("test[%d]: unexpected success, got %#x %#x %#x", testNo, sigAlg, sigType, hashFunc) + } + } +} diff --git a/libgo/go/crypto/tls/cipher_suites.go b/libgo/go/crypto/tls/cipher_suites.go index beb0f1926d8..3c8dc4b2d29 100644 --- a/libgo/go/crypto/tls/cipher_suites.go +++ b/libgo/go/crypto/tls/cipher_suites.go @@ -333,14 +333,14 @@ func rsaKA(version uint16) keyAgreement { func ecdheECDSAKA(version uint16) keyAgreement { return &ecdheKeyAgreement{ - sigType: signatureECDSA, + isRSA: false, version: version, } } func ecdheRSAKA(version uint16) keyAgreement { return &ecdheKeyAgreement{ - sigType: signatureRSA, + isRSA: true, version: version, } } @@ -364,7 +364,7 @@ func mutualCipherSuite(have []uint16, want uint16) *cipherSuite { // A list of cipher suite IDs that are, or have been, implemented by this // package. // -// Taken from http://www.iana.org/assignments/tls-parameters/tls-parameters.xml +// Taken from https://www.iana.org/assignments/tls-parameters/tls-parameters.xml const ( TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005 TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go index 646b107958a..7b627fc0253 100644 --- a/libgo/go/crypto/tls/common.go +++ b/libgo/go/crypto/tls/common.go @@ -7,12 +7,12 @@ package tls import ( "container/list" "crypto" - "crypto/internal/cipherhw" "crypto/rand" "crypto/sha512" "crypto/x509" "errors" "fmt" + "internal/cpu" "io" "math/big" "net" @@ -91,7 +91,7 @@ const ( ) // CurveID is the type of a TLS identifier for an elliptic curve. See -// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 +// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8 type CurveID uint16 const ( @@ -102,7 +102,7 @@ const ( ) // TLS Elliptic Curve Point Formats -// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 +// https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9 const ( pointFormatUncompressed uint8 = 0 ) @@ -127,10 +127,12 @@ const ( // Rest of these are reserved by the TLS spec ) -// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1) +// Signature algorithms (for internal signaling use). Starting at 16 to avoid overlap with +// TLS 1.2 codepoints (RFC 5246, section A.4.1), with which these have nothing to do. const ( - signatureRSA uint8 = 1 - signatureECDSA uint8 = 3 + signaturePKCS1v15 uint8 = iota + 16 + signatureECDSA + signatureRSAPSS ) // supportedSignatureAlgorithms contains the signature and hash algorithms that @@ -162,6 +164,9 @@ type ConnectionState struct { SignedCertificateTimestamps [][]byte // SCTs from the server, if any OCSPResponse []byte // stapled OCSP response from server, if any + // ekm is a closure exposed via ExportKeyingMaterial. + ekm func(label string, context []byte, length int) ([]byte, error) + // TLSUnique contains the "tls-unique" channel binding value (see RFC // 5929, section 3). For resumed sessions this value will be nil // because resumption does not include enough context (see @@ -171,6 +176,14 @@ type ConnectionState struct { TLSUnique []byte } +// ExportKeyingMaterial returns length bytes of exported key material in a new +// slice as defined in https://tools.ietf.org/html/rfc5705. If context is nil, +// it is not used as part of the seed. If the connection was set to allow +// renegotiation via Config.Renegotiation, this function will return an error. +func (cs *ConnectionState) ExportKeyingMaterial(label string, context []byte, length int) ([]byte, error) { + return cs.ekm(label, context, length) +} + // ClientAuthType declares the policy the server will follow for // TLS Client Authentication. type ClientAuthType int @@ -240,19 +253,19 @@ type ClientHelloInfo struct { // ServerName indicates the name of the server requested by the client // in order to support virtual hosting. ServerName is only set if the // client is using SNI (see - // http://tools.ietf.org/html/rfc4366#section-3.1). + // https://tools.ietf.org/html/rfc4366#section-3.1). ServerName string // SupportedCurves lists the elliptic curves supported by the client. // SupportedCurves is set only if the Supported Elliptic Curves // Extension is being used (see - // http://tools.ietf.org/html/rfc4492#section-5.1.1). + // https://tools.ietf.org/html/rfc4492#section-5.1.1). SupportedCurves []CurveID // SupportedPoints lists the point formats supported by the client. // SupportedPoints is set only if the Supported Point Formats Extension // is being used (see - // http://tools.ietf.org/html/rfc4492#section-5.1.2). + // https://tools.ietf.org/html/rfc4492#section-5.1.2). SupportedPoints []uint8 // SignatureSchemes lists the signature and hash schemes that the client @@ -453,7 +466,8 @@ type Config struct { PreferServerCipherSuites bool // SessionTicketsDisabled may be set to true to disable session ticket - // (resumption) support. + // (resumption) support. Note that on clients, session ticket support is + // also disabled if ClientSessionCache is nil. SessionTicketsDisabled bool // SessionTicketKey is used by TLS servers to provide session @@ -467,7 +481,7 @@ type Config struct { SessionTicketKey [32]byte // ClientSessionCache is a cache of ClientSessionState entries for TLS - // session resumption. + // session resumption. It is only used by clients. ClientSessionCache ClientSessionCache // MinVersion contains the minimum SSL/TLS version that is acceptable. @@ -911,7 +925,19 @@ func defaultCipherSuites() []uint16 { func initDefaultCipherSuites() { var topCipherSuites []uint16 - if cipherhw.AESGCMSupport() { + + // Check the cpu flags for each platform that has optimized GCM implementations. + // Worst case, these variables will just all be false + 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) + + hasGCMAsm := hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X + + if hasGCMAsm { // If AES-GCM hardware is provided then prioritise AES-GCM // cipher suites. topCipherSuites = []uint16{ @@ -970,7 +996,9 @@ func isSupportedSignatureAlgorithm(sigAlg SignatureScheme, supportedSignatureAlg func signatureFromSignatureScheme(signatureAlgorithm SignatureScheme) uint8 { switch signatureAlgorithm { case PKCS1WithSHA1, PKCS1WithSHA256, PKCS1WithSHA384, PKCS1WithSHA512: - return signatureRSA + return signaturePKCS1v15 + case PSSWithSHA256, PSSWithSHA384, PSSWithSHA512: + return signatureRSAPSS case ECDSAWithSHA1, ECDSAWithP256AndSHA256, ECDSAWithP384AndSHA384, ECDSAWithP521AndSHA512: return signatureECDSA default: diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go index 31c50538703..6e27e695bd8 100644 --- a/libgo/go/crypto/tls/conn.go +++ b/libgo/go/crypto/tls/conn.go @@ -27,19 +27,16 @@ type Conn struct { conn net.Conn isClient bool - // constant after handshake; protected by handshakeMutex - handshakeMutex sync.Mutex // handshakeMutex < in.Mutex, out.Mutex, errMutex - // handshakeCond, if not nil, indicates that a goroutine is committed - // to running the handshake for this Conn. Other goroutines that need - // to wait for the handshake can wait on this, under handshakeMutex. - handshakeCond *sync.Cond - handshakeErr error // error resulting from handshake - vers uint16 // TLS version - haveVers bool // version has been negotiated - config *Config // configuration passed to constructor - // handshakeComplete is true if the connection is currently transferring + // handshakeStatus is 1 if the connection is currently transferring // application data (i.e. is not currently processing a handshake). - handshakeComplete bool + // This field is only to be accessed with sync/atomic. + handshakeStatus uint32 + // constant after handshake; protected by handshakeMutex + handshakeMutex sync.Mutex + handshakeErr error // error resulting from handshake + vers uint16 // TLS version + haveVers bool // version has been negotiated + config *Config // configuration passed to constructor // handshakes counts the number of handshakes performed on the // connection so far. If renegotiation is disabled then this is either // zero or one. @@ -58,6 +55,8 @@ type Conn struct { // renegotiation extension. (This is meaningless as a server because // renegotiation is not supported in that case.) secureRenegotiation bool + // ekm is a closure for exporting keying material. + ekm func(label string, context []byte, length int) ([]byte, error) // clientFinishedIsFirst is true if the client sent the first Finished // message during the most recent handshake. This is recorded because @@ -82,7 +81,7 @@ type Conn struct { clientProtocolFallback bool // input/output - in, out halfConn // in.Mutex < out.Mutex + in, out halfConn rawInput *block // raw input, right off the wire input *block // application data waiting to be read hand bytes.Buffer // handshake data waiting to be read @@ -564,7 +563,6 @@ func (c *Conn) newRecordHeaderError(msg string) (err RecordHeaderError) { // readRecord reads the next TLS record from the connection // and updates the record layer state. -// c.in.Mutex <= L; c.input == nil. func (c *Conn) readRecord(want recordType) error { // Caller must be in sync with connection: // handshake data if handshake not yet completed, @@ -574,12 +572,12 @@ func (c *Conn) readRecord(want recordType) error { c.sendAlert(alertInternalError) return c.in.setErrorLocked(errors.New("tls: unknown record type requested")) case recordTypeHandshake, recordTypeChangeCipherSpec: - if c.handshakeComplete { + if c.handshakeComplete() { c.sendAlert(alertInternalError) return c.in.setErrorLocked(errors.New("tls: handshake or ChangeCipherSpec requested while not in handshake")) } case recordTypeApplicationData: - if !c.handshakeComplete { + if !c.handshakeComplete() { c.sendAlert(alertInternalError) return c.in.setErrorLocked(errors.New("tls: application data record requested while in handshake")) } @@ -736,7 +734,6 @@ Again: } // sendAlert sends a TLS alert message. -// c.out.Mutex <= L. func (c *Conn) sendAlertLocked(err alert) error { switch err { case alertNoRenegotiation, alertCloseNotify: @@ -756,7 +753,6 @@ func (c *Conn) sendAlertLocked(err alert) error { } // sendAlert sends a TLS alert message. -// L < c.out.Mutex. func (c *Conn) sendAlert(err alert) error { c.out.Lock() defer c.out.Unlock() @@ -793,8 +789,6 @@ const ( // // In the interests of simplicity and determinism, this code does not attempt // to reset the record size once the connection is idle, however. -// -// c.out.Mutex <= L. func (c *Conn) maxPayloadSizeForWrite(typ recordType, explicitIVLen int) int { if c.config.DynamicRecordSizingDisabled || typ != recordTypeApplicationData { return maxPlaintext @@ -844,7 +838,6 @@ func (c *Conn) maxPayloadSizeForWrite(typ recordType, explicitIVLen int) int { return n } -// c.out.Mutex <= L. func (c *Conn) write(data []byte) (int, error) { if c.buffering { c.sendBuf = append(c.sendBuf, data...) @@ -870,7 +863,6 @@ func (c *Conn) flush() (int, error) { // writeRecordLocked writes a TLS record with the given type and payload to the // connection and updates the record layer state. -// c.out.Mutex <= L. func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) { b := c.out.newBlock() defer c.out.freeBlock(b) @@ -946,7 +938,6 @@ func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) { // writeRecord writes a TLS record with the given type and payload to the // connection and updates the record layer state. -// L < c.out.Mutex. func (c *Conn) writeRecord(typ recordType, data []byte) (int, error) { c.out.Lock() defer c.out.Unlock() @@ -956,7 +947,6 @@ func (c *Conn) writeRecord(typ recordType, data []byte) (int, error) { // readHandshake reads the next handshake message from // the record layer. -// c.in.Mutex < L; c.out.Mutex < L. func (c *Conn) readHandshake() (interface{}, error) { for c.hand.Len() < 4 { if err := c.in.err; err != nil { @@ -1059,7 +1049,7 @@ func (c *Conn) Write(b []byte) (int, error) { return 0, err } - if !c.handshakeComplete { + if !c.handshakeComplete() { return 0, alertInternalError } @@ -1072,9 +1062,9 @@ func (c *Conn) Write(b []byte) (int, error) { // This can be prevented by splitting each Application Data // record into two records, effectively randomizing the IV. // - // http://www.openssl.org/~bodo/tls-cbc.txt + // https://www.openssl.org/~bodo/tls-cbc.txt // https://bugzilla.mozilla.org/show_bug.cgi?id=665814 - // http://www.imperialviolet.org/2012/01/15/beastfollowup.html + // https://www.imperialviolet.org/2012/01/15/beastfollowup.html var m int if len(b) > 1 && c.vers <= VersionTLS10 { @@ -1092,7 +1082,6 @@ func (c *Conn) Write(b []byte) (int, error) { } // handleRenegotiation processes a HelloRequest handshake message. -// c.in.Mutex <= L func (c *Conn) handleRenegotiation() error { msg, err := c.readHandshake() if err != nil { @@ -1126,7 +1115,7 @@ func (c *Conn) handleRenegotiation() error { c.handshakeMutex.Lock() defer c.handshakeMutex.Unlock() - c.handshakeComplete = false + atomic.StoreUint32(&c.handshakeStatus, 0) if c.handshakeErr = c.clientHandshake(); c.handshakeErr == nil { c.handshakes++ } @@ -1227,11 +1216,9 @@ func (c *Conn) Close() error { var alertErr error - c.handshakeMutex.Lock() - if c.handshakeComplete { + if c.handshakeComplete() { alertErr = c.closeNotify() } - c.handshakeMutex.Unlock() if err := c.conn.Close(); err != nil { return err @@ -1245,9 +1232,7 @@ var errEarlyCloseWrite = errors.New("tls: CloseWrite called before handshake com // called once the handshake has completed and does not call CloseWrite on the // underlying connection. Most callers should just use Close. func (c *Conn) CloseWrite() error { - c.handshakeMutex.Lock() - defer c.handshakeMutex.Unlock() - if !c.handshakeComplete { + if !c.handshakeComplete() { return errEarlyCloseWrite } @@ -1270,61 +1255,19 @@ func (c *Conn) closeNotify() error { // Most uses of this package need not call Handshake // explicitly: the first Read or Write will call it automatically. func (c *Conn) Handshake() error { - // c.handshakeErr and c.handshakeComplete are protected by - // c.handshakeMutex. In order to perform a handshake, we need to lock - // c.in also and c.handshakeMutex must be locked after c.in. - // - // However, if a Read() operation is hanging then it'll be holding the - // lock on c.in and so taking it here would cause all operations that - // need to check whether a handshake is pending (such as Write) to - // block. - // - // Thus we first take c.handshakeMutex to check whether a handshake is - // needed. - // - // If so then, previously, this code would unlock handshakeMutex and - // then lock c.in and handshakeMutex in the correct order to run the - // handshake. The problem was that it was possible for a Read to - // complete the handshake once handshakeMutex was unlocked and then - // keep c.in while waiting for network data. Thus a concurrent - // operation could be blocked on c.in. - // - // Thus handshakeCond is used to signal that a goroutine is committed - // to running the handshake and other goroutines can wait on it if they - // need. handshakeCond is protected by handshakeMutex. c.handshakeMutex.Lock() defer c.handshakeMutex.Unlock() - for { - if err := c.handshakeErr; err != nil { - return err - } - if c.handshakeComplete { - return nil - } - if c.handshakeCond == nil { - break - } - - c.handshakeCond.Wait() + if err := c.handshakeErr; err != nil { + return err + } + if c.handshakeComplete() { + return nil } - - // Set handshakeCond to indicate that this goroutine is committing to - // running the handshake. - c.handshakeCond = sync.NewCond(&c.handshakeMutex) - c.handshakeMutex.Unlock() c.in.Lock() defer c.in.Unlock() - c.handshakeMutex.Lock() - - // The handshake cannot have completed when handshakeMutex was unlocked - // because this goroutine set handshakeCond. - if c.handshakeErr != nil || c.handshakeComplete { - panic("handshake should not have been able to complete after handshakeCond was set") - } - if c.isClient { c.handshakeErr = c.clientHandshake() } else { @@ -1338,15 +1281,10 @@ func (c *Conn) Handshake() error { c.flush() } - if c.handshakeErr == nil && !c.handshakeComplete { + if c.handshakeErr == nil && !c.handshakeComplete() { panic("handshake should have had a result.") } - // Wake any other goroutines that are waiting for this handshake to - // complete. - c.handshakeCond.Broadcast() - c.handshakeCond = nil - return c.handshakeErr } @@ -1356,10 +1294,10 @@ func (c *Conn) ConnectionState() ConnectionState { defer c.handshakeMutex.Unlock() var state ConnectionState - state.HandshakeComplete = c.handshakeComplete + state.HandshakeComplete = c.handshakeComplete() state.ServerName = c.serverName - if c.handshakeComplete { + if state.HandshakeComplete { state.Version = c.vers state.NegotiatedProtocol = c.clientProtocol state.DidResume = c.didResume @@ -1376,6 +1314,11 @@ func (c *Conn) ConnectionState() ConnectionState { state.TLSUnique = c.serverFinished[:] } } + if c.config.Renegotiation != RenegotiateNever { + state.ekm = noExportedKeyingMaterial + } else { + state.ekm = c.ekm + } } return state @@ -1399,7 +1342,7 @@ func (c *Conn) VerifyHostname(host string) error { if !c.isClient { return errors.New("tls: VerifyHostname called on TLS server connection") } - if !c.handshakeComplete { + if !c.handshakeComplete() { return errors.New("tls: handshake has not yet been performed") } if len(c.verifiedChains) == 0 { @@ -1407,3 +1350,7 @@ func (c *Conn) VerifyHostname(host string) error { } return c.peerCertificates[0].VerifyHostname(host) } + +func (c *Conn) handshakeComplete() bool { + return atomic.LoadUint32(&c.handshakeStatus) == 1 +} diff --git a/libgo/go/crypto/tls/generate_cert.go b/libgo/go/crypto/tls/generate_cert.go index 8ee2b5922b3..8d012be75c1 100644 --- a/libgo/go/crypto/tls/generate_cert.go +++ b/libgo/go/crypto/tls/generate_cert.go @@ -146,16 +146,24 @@ func main() { if err != nil { log.Fatalf("failed to open cert.pem for writing: %s", err) } - pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) - certOut.Close() - log.Print("written cert.pem\n") + if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { + log.Fatalf("failed to write data to cert.pem: %s", err) + } + if err := certOut.Close(); err != nil { + log.Fatalf("error closing cert.pem: %s", err) + } + log.Print("wrote cert.pem\n") keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { log.Print("failed to open key.pem for writing:", err) return } - pem.Encode(keyOut, pemBlockForKey(priv)) - keyOut.Close() - log.Print("written key.pem\n") + if err := pem.Encode(keyOut, pemBlockForKey(priv)); err != nil { + log.Fatalf("failed to write data to key.pem: %s", err) + } + if err := keyOut.Close(); err != nil { + log.Fatalf("error closing key.pem: %s", err) + } + log.Print("wrote key.pem\n") } diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go index e5e0df2ee38..32fdc6d6eb1 100644 --- a/libgo/go/crypto/tls/handshake_client.go +++ b/libgo/go/crypto/tls/handshake_client.go @@ -17,6 +17,7 @@ import ( "net" "strconv" "strings" + "sync/atomic" ) type clientHandshakeState struct { @@ -91,7 +92,6 @@ NextCipherSuite: return hello, nil } -// c.out.Mutex <= L; c.handshakeMutex <= L. func (c *Conn) clientHandshake() error { if c.config == nil { c.config = defaultConfig() @@ -265,8 +265,9 @@ func (hs *clientHandshakeState) handshake() error { } } + c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random) c.didResume = isResume - c.handshakeComplete = true + atomic.StoreUint32(&c.handshakeStatus, 1) return nil } @@ -479,31 +480,25 @@ func (hs *clientHandshakeState) doFullHandshake() error { return fmt.Errorf("tls: client certificate private key of type %T does not implement crypto.Signer", chainToSend.PrivateKey) } - var signatureType uint8 - switch key.Public().(type) { - case *ecdsa.PublicKey: - signatureType = signatureECDSA - case *rsa.PublicKey: - signatureType = signatureRSA - default: - c.sendAlert(alertInternalError) - return fmt.Errorf("tls: failed to sign handshake with client certificate: unknown client certificate key type: %T", key) - } - - // SignatureAndHashAlgorithm was introduced in TLS 1.2. - if certVerify.hasSignatureAndHash { - certVerify.signatureAlgorithm, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.supportedSignatureAlgorithms, signatureType) - if err != nil { - c.sendAlert(alertInternalError) - return err - } - } - digest, hashFunc, err := hs.finishedHash.hashForClientCertificate(signatureType, certVerify.signatureAlgorithm, hs.masterSecret) + signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(key.Public(), certReq.supportedSignatureAlgorithms, hs.hello.supportedSignatureAlgorithms, c.vers) if err != nil { c.sendAlert(alertInternalError) return err } - certVerify.signature, err = key.Sign(c.config.rand(), digest, hashFunc) + // SignatureAndHashAlgorithm was introduced in TLS 1.2. + if certVerify.hasSignatureAndHash { + certVerify.signatureAlgorithm = signatureAlgorithm + } + digest, err := hs.finishedHash.hashForClientCertificate(sigType, hashFunc, hs.masterSecret) + if err != nil { + c.sendAlert(alertInternalError) + return err + } + signOpts := crypto.SignerOpts(hashFunc) + if sigType == signatureRSAPSS { + signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc} + } + certVerify.signature, err = key.Sign(c.config.rand(), digest, signOpts) if err != nil { c.sendAlert(alertInternalError) return err diff --git a/libgo/go/crypto/tls/handshake_client_test.go b/libgo/go/crypto/tls/handshake_client_test.go index cc3ab714a63..1f1c93d102c 100644 --- a/libgo/go/crypto/tls/handshake_client_test.go +++ b/libgo/go/crypto/tls/handshake_client_test.go @@ -979,6 +979,24 @@ func TestRenegotiateTwiceRejected(t *testing.T) { runClientTestTLS12(t, test) } +func TestHandshakeClientExportKeyingMaterial(t *testing.T) { + test := &clientTest{ + name: "ExportKeyingMaterial", + command: []string{"openssl", "s_server"}, + config: testConfig.Clone(), + validate: func(state ConnectionState) error { + if km, err := state.ExportKeyingMaterial("test", nil, 42); err != nil { + return fmt.Errorf("ExportKeyingMaterial failed: %v", err) + } else if len(km) != 42 { + return fmt.Errorf("Got %d bytes from ExportKeyingMaterial, wanted %d", len(km), 42) + } + return nil + }, + } + runClientTestTLS10(t, test) + runClientTestTLS12(t, test) +} + var hostnameInSNITests = []struct { in, out string }{ @@ -1578,3 +1596,61 @@ func TestGetClientCertificate(t *testing.T) { } } } + +func TestRSAPSSKeyError(t *testing.T) { + // crypto/tls does not support the rsa_pss_pss_xxx SignatureSchemes. If support for + // public keys with OID RSASSA-PSS is added to crypto/x509, they will be misused with + // the rsa_pss_rsae_xxx SignatureSchemes. Assert that RSASSA-PSS certificates don't + // parse, or that they don't carry *rsa.PublicKey keys. + b, _ := pem.Decode([]byte(` +-----BEGIN CERTIFICATE----- +MIIDZTCCAhygAwIBAgIUCF2x0FyTgZG0CC9QTDjGWkB5vgEwPgYJKoZIhvcNAQEK +MDGgDTALBglghkgBZQMEAgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogQC +AgDeMBIxEDAOBgNVBAMMB1JTQS1QU1MwHhcNMTgwNjI3MjI0NDM2WhcNMTgwNzI3 +MjI0NDM2WjASMRAwDgYDVQQDDAdSU0EtUFNTMIIBIDALBgkqhkiG9w0BAQoDggEP +ADCCAQoCggEBANxDm0f76JdI06YzsjB3AmmjIYkwUEGxePlafmIASFjDZl/elD0Z +/a7xLX468b0qGxLS5al7XCcEprSdsDR6DF5L520+pCbpfLyPOjuOvGmk9KzVX4x5 +b05YXYuXdsQ0Kjxcx2i3jjCday6scIhMJVgBZxTEyMj1thPQM14SHzKCd/m6HmCL +QmswpH2yMAAcBRWzRpp/vdH5DeOJEB3aelq7094no731mrLUCHRiZ1htq8BDB3ou +czwqgwspbqZ4dnMXl2MvfySQ5wJUxQwILbiuAKO2lVVPUbFXHE9pgtznNoPvKwQT +JNcX8ee8WIZc2SEGzofjk3NpjR+2ADB2u3sCAwEAAaNTMFEwHQYDVR0OBBYEFNEz +AdyJ2f+fU+vSCS6QzohnOnprMB8GA1UdIwQYMBaAFNEzAdyJ2f+fU+vSCS6Qzohn +OnprMA8GA1UdEwEB/wQFMAMBAf8wPgYJKoZIhvcNAQEKMDGgDTALBglghkgBZQME +AgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogQCAgDeA4IBAQCjEdrR5aab +sZmCwrMeKidXgfkmWvfuLDE+TCbaqDZp7BMWcMQXT9O0UoUT5kqgKj2ARm2pEW0Z +H3Z1vj3bbds72qcDIJXp+l0fekyLGeCrX/CbgnMZXEP7+/+P416p34ChR1Wz4dU1 +KD3gdsUuTKKeMUog3plxlxQDhRQmiL25ygH1LmjLd6dtIt0GVRGr8lj3euVeprqZ +bZ3Uq5eLfsn8oPgfC57gpO6yiN+UURRTlK3bgYvLh4VWB3XXk9UaQZ7Mq1tpXjoD +HYFybkWzibkZp4WRo+Fa28rirH+/wHt0vfeN7UCceURZEx4JaxIIfe4ku7uDRhJi +RwBA9Xk1KBNF +-----END CERTIFICATE-----`)) + if b == nil { + t.Fatal("Failed to decode certificate") + } + cert, err := x509.ParseCertificate(b.Bytes) + if err != nil { + return + } + if _, ok := cert.PublicKey.(*rsa.PublicKey); ok { + t.Error("A RSA-PSS certificate was parsed like a PKCS1 one, and it will be mistakenly used with rsa_pss_rsae_xxx signature algorithms") + } +} + +func TestCloseClientConnectionOnIdleServer(t *testing.T) { + clientConn, serverConn := net.Pipe() + client := Client(clientConn, testConfig.Clone()) + go func() { + var b [1]byte + serverConn.Read(b[:]) + client.Close() + }() + client.SetWriteDeadline(time.Now().Add(time.Second)) + err := client.Handshake() + if err != nil { + if !strings.Contains(err.Error(), "read/write on closed pipe") { + t.Errorf("Error expected containing 'read/write on closed pipe' but got '%s'", err.Error()) + } + } else { + t.Errorf("Error expected, but no error returned") + } +} diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go index f8c8d571ccd..a5bf10efb8c 100644 --- a/libgo/go/crypto/tls/handshake_messages.go +++ b/libgo/go/crypto/tls/handshake_messages.go @@ -192,7 +192,7 @@ func (m *clientHelloMsg) marshal() []byte { z = z[9:] } if len(m.supportedCurves) > 0 { - // http://tools.ietf.org/html/rfc4492#section-5.5.1 + // https://tools.ietf.org/html/rfc4492#section-5.5.1 z[0] = byte(extensionSupportedCurves >> 8) z[1] = byte(extensionSupportedCurves) l := 2 + 2*len(m.supportedCurves) @@ -209,7 +209,7 @@ func (m *clientHelloMsg) marshal() []byte { } } if len(m.supportedPoints) > 0 { - // http://tools.ietf.org/html/rfc4492#section-5.5.2 + // https://tools.ietf.org/html/rfc4492#section-5.5.2 z[0] = byte(extensionSupportedPoints >> 8) z[1] = byte(extensionSupportedPoints) l := 1 + len(m.supportedPoints) @@ -224,7 +224,7 @@ func (m *clientHelloMsg) marshal() []byte { } } if m.ticketSupported { - // http://tools.ietf.org/html/rfc5077#section-3.2 + // https://tools.ietf.org/html/rfc5077#section-3.2 z[0] = byte(extensionSessionTicket >> 8) z[1] = byte(extensionSessionTicket) l := len(m.sessionTicket) @@ -414,7 +414,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { case extensionStatusRequest: m.ocspStapling = length > 0 && data[0] == statusTypeOCSP case extensionSupportedCurves: - // http://tools.ietf.org/html/rfc4492#section-5.5.1 + // https://tools.ietf.org/html/rfc4492#section-5.5.1 if length < 2 { return false } @@ -430,7 +430,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { d = d[2:] } case extensionSupportedPoints: - // http://tools.ietf.org/html/rfc4492#section-5.5.2 + // https://tools.ietf.org/html/rfc4492#section-5.5.2 if length < 1 { return false } @@ -441,7 +441,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { m.supportedPoints = make([]uint8, l) copy(m.supportedPoints, data[1:]) case extensionSessionTicket: - // http://tools.ietf.org/html/rfc5077#section-3.2 + // https://tools.ietf.org/html/rfc5077#section-3.2 m.ticketSupported = true m.sessionTicket = data[:length] case extensionSignatureAlgorithms: @@ -1224,7 +1224,7 @@ func (m *certificateRequestMsg) marshal() (x []byte) { return m.raw } - // See http://tools.ietf.org/html/rfc4346#section-7.4.4 + // See https://tools.ietf.org/html/rfc4346#section-7.4.4 length := 1 + len(m.certificateTypes) + 2 casLength := 0 for _, ca := range m.certificateAuthorities { @@ -1374,7 +1374,7 @@ func (m *certificateVerifyMsg) marshal() (x []byte) { return m.raw } - // See http://tools.ietf.org/html/rfc4346#section-7.4.8 + // See https://tools.ietf.org/html/rfc4346#section-7.4.8 siglength := len(m.signature) length := 2 + siglength if m.hasSignatureAndHash { @@ -1452,7 +1452,7 @@ func (m *newSessionTicketMsg) marshal() (x []byte) { return m.raw } - // See http://tools.ietf.org/html/rfc5077#section-3.3 + // See https://tools.ietf.org/html/rfc5077#section-3.3 ticketLen := len(m.ticket) length := 2 + 4 + ticketLen x = make([]byte, 4+length) diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go index 991b4e9e621..ac491bad390 100644 --- a/libgo/go/crypto/tls/handshake_server.go +++ b/libgo/go/crypto/tls/handshake_server.go @@ -10,10 +10,10 @@ import ( "crypto/rsa" "crypto/subtle" "crypto/x509" - "encoding/asn1" "errors" "fmt" "io" + "sync/atomic" ) // serverHandshakeState contains details of a server handshake in progress. @@ -36,7 +36,6 @@ type serverHandshakeState struct { } // serverHandshake performs a TLS handshake as a server. -// c.out.Mutex <= L; c.handshakeMutex <= L. func (c *Conn) serverHandshake() error { // If this is the first server handshake, we generate a random key to // encrypt the tickets with. @@ -103,7 +102,9 @@ func (c *Conn) serverHandshake() error { return err } } - c.handshakeComplete = true + + c.ekm = ekmFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random) + atomic.StoreUint32(&c.handshakeStatus, 1) return nil } @@ -519,59 +520,15 @@ func (hs *serverHandshakeState) doFullHandshake() error { } // Determine the signature type. - var signatureAlgorithm SignatureScheme - var sigType uint8 - if certVerify.hasSignatureAndHash { - signatureAlgorithm = certVerify.signatureAlgorithm - if !isSupportedSignatureAlgorithm(signatureAlgorithm, supportedSignatureAlgorithms) { - return errors.New("tls: unsupported hash function for client certificate") - } - sigType = signatureFromSignatureScheme(signatureAlgorithm) - } else { - // Before TLS 1.2 the signature algorithm was implicit - // from the key type, and only one hash per signature - // algorithm was possible. Leave signatureAlgorithm - // unset. - switch pub.(type) { - case *ecdsa.PublicKey: - sigType = signatureECDSA - case *rsa.PublicKey: - sigType = signatureRSA - } + _, sigType, hashFunc, err := pickSignatureAlgorithm(pub, []SignatureScheme{certVerify.signatureAlgorithm}, supportedSignatureAlgorithms, c.vers) + if err != nil { + c.sendAlert(alertIllegalParameter) + return err } - switch key := pub.(type) { - case *ecdsa.PublicKey: - if sigType != signatureECDSA { - err = errors.New("tls: bad signature type for client's ECDSA certificate") - break - } - ecdsaSig := new(ecdsaSignature) - if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil { - break - } - if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { - err = errors.New("tls: ECDSA signature contained zero or negative values") - break - } - var digest []byte - if digest, _, err = hs.finishedHash.hashForClientCertificate(sigType, signatureAlgorithm, hs.masterSecret); err != nil { - break - } - if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) { - err = errors.New("tls: ECDSA verification failure") - } - case *rsa.PublicKey: - if sigType != signatureRSA { - err = errors.New("tls: bad signature type for client's RSA certificate") - break - } - var digest []byte - var hashFunc crypto.Hash - if digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(sigType, signatureAlgorithm, hs.masterSecret); err != nil { - break - } - err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature) + var digest []byte + if digest, err = hs.finishedHash.hashForClientCertificate(sigType, hashFunc, hs.masterSecret); err == nil { + err = verifyHandshakeSignature(sigType, pub, hashFunc, digest, certVerify.signature) } if err != nil { c.sendAlert(alertBadCertificate) diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go index 67160213fbe..c366f47b17c 100644 --- a/libgo/go/crypto/tls/handshake_server_test.go +++ b/libgo/go/crypto/tls/handshake_server_test.go @@ -194,9 +194,9 @@ func TestDontSelectRSAWithECDSAKey(t *testing.T) { func TestRenegotiationExtension(t *testing.T) { clientHello := &clientHelloMsg{ - vers: VersionTLS12, - compressionMethods: []uint8{compressionNone}, - random: make([]byte, 32), + vers: VersionTLS12, + compressionMethods: []uint8{compressionNone}, + random: make([]byte, 32), secureRenegotiationSupported: true, cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, } @@ -992,12 +992,30 @@ func TestFallbackSCSV(t *testing.T) { name: "FallbackSCSV", config: &serverConfig, // OpenSSL 1.0.1j is needed for the -fallback_scsv option. - command: []string{"openssl", "s_client", "-fallback_scsv"}, + command: []string{"openssl", "s_client", "-fallback_scsv"}, expectHandshakeErrorIncluding: "inappropriate protocol fallback", } runServerTestTLS11(t, test) } +func TestHandshakeServerExportKeyingMaterial(t *testing.T) { + test := &serverTest{ + name: "ExportKeyingMaterial", + command: []string{"openssl", "s_client"}, + config: testConfig.Clone(), + validate: func(state ConnectionState) error { + if km, err := state.ExportKeyingMaterial("test", nil, 42); err != nil { + return fmt.Errorf("ExportKeyingMaterial failed: %v", err) + } else if len(km) != 42 { + return fmt.Errorf("Got %d bytes from ExportKeyingMaterial, wanted %d", len(km), 42) + } + return nil + }, + } + runServerTestTLS10(t, test) + runServerTestTLS12(t, test) +} + func benchmarkHandshakeServer(b *testing.B, cipherSuite uint16, curve CurveID, cert []byte, key crypto.PrivateKey) { config := testConfig.Clone() config.CipherSuites = []uint16{cipherSuite} @@ -1403,3 +1421,21 @@ var testECDSAPrivateKey = &ecdsa.PrivateKey{ } var testP256PrivateKey, _ = x509.ParseECPrivateKey(fromHex("30770201010420012f3b52bc54c36ba3577ad45034e2e8efe1e6999851284cb848725cfe029991a00a06082a8648ce3d030107a14403420004c02c61c9b16283bbcc14956d886d79b358aa614596975f78cece787146abf74c2d5dc578c0992b4f3c631373479ebf3892efe53d21c4f4f1cc9a11c3536b7f75")) + +func TestCloseServerConnectionOnIdleClient(t *testing.T) { + clientConn, serverConn := net.Pipe() + server := Server(serverConn, testConfig.Clone()) + go func() { + clientConn.Write([]byte{'0'}) + server.Close() + }() + server.SetReadDeadline(time.Now().Add(time.Second)) + err := server.Handshake() + if err != nil { + if !strings.Contains(err.Error(), "read/write on closed pipe") { + t.Errorf("Error expected containing 'read/write on closed pipe' but got '%s'", err.Error()) + } + } else { + t.Errorf("Error expected, but no error returned") + } +} diff --git a/libgo/go/crypto/tls/key_agreement.go b/libgo/go/crypto/tls/key_agreement.go index 3f570b66c69..1e77facce07 100644 --- a/libgo/go/crypto/tls/key_agreement.go +++ b/libgo/go/crypto/tls/key_agreement.go @@ -6,13 +6,11 @@ package tls import ( "crypto" - "crypto/ecdsa" "crypto/elliptic" "crypto/md5" "crypto/rsa" "crypto/sha1" "crypto/x509" - "encoding/asn1" "errors" "io" "math/big" @@ -110,58 +108,21 @@ func md5SHA1Hash(slices [][]byte) []byte { } // hashForServerKeyExchange hashes the given slices and returns their digest -// and the identifier of the hash function used. The signatureAlgorithm argument -// is only used for >= TLS 1.2 and identifies the hash function to use. -func hashForServerKeyExchange(sigType uint8, signatureAlgorithm SignatureScheme, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) { +// using the given hash function (for >= TLS 1.2) or using a default based on +// the sigType (for earlier TLS versions). +func hashForServerKeyExchange(sigType uint8, hashFunc crypto.Hash, version uint16, slices ...[]byte) ([]byte, error) { if version >= VersionTLS12 { - if !isSupportedSignatureAlgorithm(signatureAlgorithm, supportedSignatureAlgorithms) { - return nil, crypto.Hash(0), errors.New("tls: unsupported hash function used by peer") - } - hashFunc, err := lookupTLSHash(signatureAlgorithm) - if err != nil { - return nil, crypto.Hash(0), err - } h := hashFunc.New() for _, slice := range slices { h.Write(slice) } digest := h.Sum(nil) - return digest, hashFunc, nil + return digest, nil } if sigType == signatureECDSA { - return sha1Hash(slices), crypto.SHA1, nil + return sha1Hash(slices), nil } - return md5SHA1Hash(slices), crypto.MD5SHA1, nil -} - -// pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a -// ServerKeyExchange given the signature type being used and the client's -// advertised list of supported signature and hash combinations. -func pickTLS12HashForSignature(sigType uint8, clientList []SignatureScheme) (SignatureScheme, error) { - if len(clientList) == 0 { - // If the client didn't specify any signature_algorithms - // extension then we can assume that it supports SHA1. See - // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 - switch sigType { - case signatureRSA: - return PKCS1WithSHA1, nil - case signatureECDSA: - return ECDSAWithSHA1, nil - default: - return 0, errors.New("tls: unknown signature algorithm") - } - } - - for _, sigAlg := range clientList { - if signatureFromSignatureScheme(sigAlg) != sigType { - continue - } - if isSupportedSignatureAlgorithm(sigAlg, supportedSignatureAlgorithms) { - return sigAlg, nil - } - } - - return 0, errors.New("tls: client doesn't support any common hash functions") + return md5SHA1Hash(slices), nil } func curveForCurveID(id CurveID) (elliptic.Curve, bool) { @@ -178,13 +139,13 @@ func curveForCurveID(id CurveID) (elliptic.Curve, bool) { } -// ecdheRSAKeyAgreement implements a TLS key agreement where the server +// ecdheKeyAgreement implements a TLS key agreement where the server // generates an ephemeral EC public/private key pair and signs it. The // pre-master secret is then calculated using ECDH. The signature may // either be ECDSA or RSA. type ecdheKeyAgreement struct { version uint16 - sigType uint8 + isRSA bool privateKey []byte curveid CurveID @@ -239,7 +200,7 @@ NextCandidate: ecdhePublic = elliptic.Marshal(curve, x, y) } - // http://tools.ietf.org/html/rfc4492#section-5.4 + // https://tools.ietf.org/html/rfc4492#section-5.4 serverECDHParams := make([]byte, 1+2+1+len(ecdhePublic)) serverECDHParams[0] = 3 // named curve serverECDHParams[1] = byte(ka.curveid >> 8) @@ -247,41 +208,29 @@ NextCandidate: serverECDHParams[3] = byte(len(ecdhePublic)) copy(serverECDHParams[4:], ecdhePublic) - var signatureAlgorithm SignatureScheme - - if ka.version >= VersionTLS12 { - var err error - signatureAlgorithm, err = pickTLS12HashForSignature(ka.sigType, clientHello.supportedSignatureAlgorithms) - if err != nil { - return nil, err - } - } - - digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, signatureAlgorithm, ka.version, clientHello.random, hello.random, serverECDHParams) - if err != nil { - return nil, err - } - priv, ok := cert.PrivateKey.(crypto.Signer) if !ok { return nil, errors.New("tls: certificate private key does not implement crypto.Signer") } - var sig []byte - switch ka.sigType { - case signatureECDSA: - _, ok := priv.Public().(*ecdsa.PublicKey) - if !ok { - return nil, errors.New("tls: ECDHE ECDSA requires an ECDSA server key") - } - case signatureRSA: - _, ok := priv.Public().(*rsa.PublicKey) - if !ok { - return nil, errors.New("tls: ECDHE RSA requires a RSA server key") - } - default: - return nil, errors.New("tls: unknown ECDHE signature algorithm") + + signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(priv.Public(), clientHello.supportedSignatureAlgorithms, supportedSignatureAlgorithms, ka.version) + if err != nil { + return nil, err } - sig, err = priv.Sign(config.rand(), digest, hashFunc) + if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA { + return nil, errors.New("tls: certificate cannot be used with the selected cipher suite") + } + + digest, err := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, hello.random, serverECDHParams) + if err != nil { + return nil, err + } + + signOpts := crypto.SignerOpts(hashFunc) + if sigType == signatureRSAPSS { + signOpts = &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash, Hash: hashFunc} + } + sig, err := priv.Sign(config.rand(), digest, signOpts) if err != nil { return nil, errors.New("tls: failed to sign ECDHE parameters: " + err.Error()) } @@ -380,53 +329,30 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell if ka.version >= VersionTLS12 { // handle SignatureAndHashAlgorithm signatureAlgorithm = SignatureScheme(sig[0])<<8 | SignatureScheme(sig[1]) - if signatureFromSignatureScheme(signatureAlgorithm) != ka.sigType { - return errServerKeyExchange - } sig = sig[2:] if len(sig) < 2 { return errServerKeyExchange } } + _, sigType, hashFunc, err := pickSignatureAlgorithm(cert.PublicKey, []SignatureScheme{signatureAlgorithm}, clientHello.supportedSignatureAlgorithms, ka.version) + if err != nil { + return err + } + if (sigType == signaturePKCS1v15 || sigType == signatureRSAPSS) != ka.isRSA { + return errServerKeyExchange + } + sigLen := int(sig[0])<<8 | int(sig[1]) if sigLen+2 != len(sig) { return errServerKeyExchange } sig = sig[2:] - digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, signatureAlgorithm, ka.version, clientHello.random, serverHello.random, serverECDHParams) + digest, err := hashForServerKeyExchange(sigType, hashFunc, ka.version, clientHello.random, serverHello.random, serverECDHParams) if err != nil { return err } - switch ka.sigType { - case signatureECDSA: - pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey) - if !ok { - return errors.New("tls: ECDHE ECDSA requires a ECDSA server public key") - } - ecdsaSig := new(ecdsaSignature) - if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil { - return err - } - if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 { - return errors.New("tls: ECDSA signature contained zero or negative values") - } - if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) { - return errors.New("tls: ECDSA verification failure") - } - case signatureRSA: - pubKey, ok := cert.PublicKey.(*rsa.PublicKey) - if !ok { - return errors.New("tls: ECDHE RSA requires a RSA server public key") - } - if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil { - return err - } - default: - return errors.New("tls: unknown ECDHE signature algorithm") - } - - return nil + return verifyHandshakeSignature(sigType, cert.PublicKey, hashFunc, digest, sig) } func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) { diff --git a/libgo/go/crypto/tls/prf.go b/libgo/go/crypto/tls/prf.go index 74438f8bc84..a8cf21da15f 100644 --- a/libgo/go/crypto/tls/prf.go +++ b/libgo/go/crypto/tls/prf.go @@ -140,7 +140,7 @@ func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, labe } // masterFromPreMasterSecret generates the master secret from the pre-master -// secret. See http://tools.ietf.org/html/rfc5246#section-8.1 +// secret. See https://tools.ietf.org/html/rfc5246#section-8.1 func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte { seed := make([]byte, 0, len(clientRandom)+len(serverRandom)) seed = append(seed, clientRandom...) @@ -309,50 +309,35 @@ func (h finishedHash) serverSum(masterSecret []byte) []byte { return out } -// selectClientCertSignatureAlgorithm returns a SignatureScheme to sign a -// client's CertificateVerify with, or an error if none can be found. -func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []SignatureScheme, sigType uint8) (SignatureScheme, error) { - for _, v := range serverList { - if signatureFromSignatureScheme(v) == sigType && isSupportedSignatureAlgorithm(v, supportedSignatureAlgorithms) { - return v, nil - } - } - return 0, errors.New("tls: no supported signature algorithm found for signing client certificate") -} - -// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash -// id suitable for signing by a TLS client certificate. -func (h finishedHash) hashForClientCertificate(sigType uint8, signatureAlgorithm SignatureScheme, masterSecret []byte) ([]byte, crypto.Hash, error) { +// hashForClientCertificate returns a digest over the handshake messages so far, +// suitable for signing by a TLS client certificate. +func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Hash, masterSecret []byte) ([]byte, error) { if (h.version == VersionSSL30 || h.version >= VersionTLS12) && h.buffer == nil { panic("a handshake hash for a client-certificate was requested after discarding the handshake buffer") } if h.version == VersionSSL30 { - if sigType != signatureRSA { - return nil, 0, errors.New("tls: unsupported signature type for client certificate") + if sigType != signaturePKCS1v15 { + return nil, errors.New("tls: unsupported signature type for client certificate") } md5Hash := md5.New() md5Hash.Write(h.buffer) sha1Hash := sha1.New() sha1Hash.Write(h.buffer) - return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil + return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), nil } if h.version >= VersionTLS12 { - hashAlg, err := lookupTLSHash(signatureAlgorithm) - if err != nil { - return nil, 0, err - } hash := hashAlg.New() hash.Write(h.buffer) - return hash.Sum(nil), hashAlg, nil + return hash.Sum(nil), nil } if sigType == signatureECDSA { - return h.server.Sum(nil), crypto.SHA1, nil + return h.server.Sum(nil), nil } - return h.Sum(), crypto.MD5SHA1, nil + return h.Sum(), nil } // discardHandshakeBuffer is called when there is no more need to @@ -360,3 +345,43 @@ func (h finishedHash) hashForClientCertificate(sigType uint8, signatureAlgorithm func (h *finishedHash) discardHandshakeBuffer() { h.buffer = nil } + +// noExportedKeyingMaterial is used as a value of +// ConnectionState.ekm when renegotation is enabled and thus +// we wish to fail all key-material export requests. +func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, error) { + return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled") +} + +// ekmFromMasterSecret generates exported keying material as defined in +// https://tools.ietf.org/html/rfc5705. +func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) { + return func(label string, context []byte, length int) ([]byte, error) { + switch label { + case "client finished", "server finished", "master secret", "key expansion": + // These values are reserved and may not be used. + return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label) + } + + seedLen := len(serverRandom) + len(clientRandom) + if context != nil { + seedLen += 2 + len(context) + } + seed := make([]byte, 0, seedLen) + + seed = append(seed, clientRandom...) + seed = append(seed, serverRandom...) + + if context != nil { + if len(context) >= 1<<16 { + return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long") + } + seed = append(seed, byte(len(context)>>8), byte(len(context))) + seed = append(seed, context...) + } + + keyMaterial := make([]byte, length) + prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed) + return keyMaterial, nil + } +} diff --git a/libgo/go/crypto/tls/prf_test.go b/libgo/go/crypto/tls/prf_test.go index 0a1b1bcbd1b..f201253f72e 100644 --- a/libgo/go/crypto/tls/prf_test.go +++ b/libgo/go/crypto/tls/prf_test.go @@ -34,14 +34,15 @@ func TestSplitPreMasterSecret(t *testing.T) { } type testKeysFromTest struct { - version uint16 - suite *cipherSuite - preMasterSecret string - clientRandom, serverRandom string - masterSecret string - clientMAC, serverMAC string - clientKey, serverKey string - macLen, keyLen int + version uint16 + suite *cipherSuite + preMasterSecret string + clientRandom, serverRandom string + masterSecret string + clientMAC, serverMAC string + clientKey, serverKey string + macLen, keyLen int + contextKeyingMaterial, noContextKeyingMaterial string } func TestKeysFromPreMasterSecret(t *testing.T) { @@ -67,6 +68,22 @@ func TestKeysFromPreMasterSecret(t *testing.T) { serverKeyString != test.serverKey { t.Errorf("#%d: got: (%s, %s, %s, %s) want: (%s, %s, %s, %s)", i, clientMACString, serverMACString, clientKeyString, serverKeyString, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey) } + + ekm := ekmFromMasterSecret(test.version, test.suite, masterSecret, clientRandom, serverRandom) + contextKeyingMaterial, err := ekm("label", []byte("context"), 32) + if err != nil { + t.Fatalf("ekmFromMasterSecret failed: %v", err) + } + + noContextKeyingMaterial, err := ekm("label", nil, 32) + if err != nil { + t.Fatalf("ekmFromMasterSecret failed: %v", err) + } + + if hex.EncodeToString(contextKeyingMaterial) != test.contextKeyingMaterial || + hex.EncodeToString(noContextKeyingMaterial) != test.noContextKeyingMaterial { + t.Errorf("#%d: got keying material: (%s, %s) want: (%s, %s)", i, contextKeyingMaterial, noContextKeyingMaterial, test.contextKeyingMaterial, test.noContextKeyingMaterial) + } } } @@ -94,6 +111,8 @@ var testKeysFromTests = []testKeysFromTest{ "e076e33206b30507a85c32855acd0919", 20, 16, + "4d1bb6fc278c37d27aa6e2a13c2e079095d143272c2aa939da33d88c1c0cec22", + "93fba89599b6321ae538e27c6548ceb8b46821864318f5190d64a375e5d69d41", }, { VersionTLS10, @@ -108,6 +127,8 @@ var testKeysFromTests = []testKeysFromTest{ "df3f94f6e1eacc753b815fe16055cd43", 20, 16, + "2c9f8961a72b97cbe76553b5f954caf8294fc6360ef995ac1256fe9516d0ce7f", + "274f19c10291d188857ad8878e2119f5aa437d4da556601cf1337aff23154016", }, { VersionTLS10, @@ -122,6 +143,8 @@ var testKeysFromTests = []testKeysFromTest{ "ff07edde49682b45466bd2e39464b306", 20, 16, + "678b0d43f607de35241dc7e9d1a7388a52c35033a1a0336d4d740060a6638fe2", + "f3b4ac743f015ef21d79978297a53da3e579ee047133f38c234d829c0f907dab", }, { VersionSSL30, @@ -136,5 +159,7 @@ var testKeysFromTests = []testKeysFromTest{ "2b9d4b4a60cb7f396780ebff50650419", 20, 16, + "d230d8fc4f695be60368635e5268c414ca3ae0995dd93aba9f877272049f35bf", + "6b5e9646e04df8e99482a9b22dbfbe42ddd4725e4b041d02d11e4ef44ad13120", }, } diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial b/libgo/go/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial new file mode 100644 index 00000000000..571769e125d --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv10-ExportKeyingMaterial @@ -0,0 +1,89 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 95 01 00 00 91 03 03 00 00 00 00 00 |................| +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 00 00 2c cc a8 |.............,..| +00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| +00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| +00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 3c 00 05 |.............<..| +00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................| +00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 12 00 |................| +00000080 10 04 01 04 03 05 01 05 03 06 01 06 03 02 01 02 |................| +00000090 03 ff 01 00 01 00 00 12 00 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 01 00 59 02 00 00 55 03 01 67 4f 02 da 87 |....Y...U..gO...| +00000010 52 30 9a f0 3b e0 63 42 bf 6c 18 58 00 06 70 cf |R0..;.cB.l.X..p.| +00000020 2a 27 5a 00 a7 57 49 fe 03 dd 3b 20 7c 2c 74 00 |*'Z..WI...; |,t.| +00000030 6e b2 35 ca 1b b5 8c 46 f7 78 ab 11 92 43 8c f6 |n.5....F.x...C..| +00000040 97 d3 b8 07 4c 9c 95 2b 08 fe e8 82 c0 13 00 00 |....L..+........| +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..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +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 a0 0e 1d 92 2d b0 a5 |........ ....-..| +000002d0 f0 ab d5 79 a0 bb 12 ff 23 46 bc 27 0d 73 ff 3e |...y....#F.'.s.>| +000002e0 ad 06 d6 57 6b c2 11 76 2d 00 80 77 bf cd 2b cb |...Wk..v-..w..+.| +000002f0 66 c2 fa 30 ed b1 e7 44 79 1b 28 e6 89 62 17 07 |f..0...Dy.(..b..| +00000300 82 c1 5f dc b2 20 4e 42 ed 54 d6 28 3a 2a e3 a3 |.._.. NB.T.(:*..| +00000310 79 06 e3 08 3c c1 3e b9 c6 41 71 2f d0 29 82 36 |y...<.>..Aq/.).6| +00000320 ef 8d 67 c8 77 d0 32 d3 33 5f 77 92 dd 98 bb 03 |..g.w.2.3_w.....| +00000330 cc 0b a6 75 8f 4a 1d f5 6e 1b 06 5b 4a 8b 16 a4 |...u.J..n..[J...| +00000340 c1 ce 11 9d 70 bc 62 7f 58 a5 86 76 91 3d 3a 04 |....p.b.X..v.=:.| +00000350 93 92 89 42 9b a7 7d 9d 75 25 6d 98 f3 e6 68 7e |...B..}.u%m...h~| +00000360 a8 c6 b1 db a7 95 63 39 94 5a 05 16 03 01 00 04 |......c9.Z......| +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 73 ad 46 66 66 e8 bd 44 e4 bf 71 |....0s.Fff..D..q| +00000040 a2 d4 87 e2 4b a3 4a b2 a0 ca ed ac 61 8c 1e 7f |....K.J.....a...| +00000050 68 bf 6f 98 b1 fb 10 1a 5a e6 36 61 91 ac c4 55 |h.o.....Z.6a...U| +00000060 a3 4d 69 66 6e |.Mifn| +>>> Flow 4 (server to client) +00000000 14 03 01 00 01 01 16 03 01 00 30 57 aa 5c d5 dc |..........0W.\..| +00000010 83 4b 23 80 34 4e 36 e8 d6 f3 40 7e ae 12 44 a6 |.K#.4N6...@~..D.| +00000020 c7 48 99 99 0a 85 3c 59 75 32 4e 88 3c 98 a0 23 |.H....>> Flow 5 (client to server) +00000000 17 03 01 00 20 e4 9c f4 fa 6b e8 85 87 6f 20 45 |.... ....k...o E| +00000010 71 d3 e2 9e e3 14 2a 7c 64 e8 11 53 fd 93 c1 4a |q.....*|d..S...J| +00000020 1b 94 f8 48 78 17 03 01 00 20 b9 41 32 1d e8 70 |...Hx.... .A2..p| +00000030 87 5f 2c c6 67 d1 77 3c 30 83 0c 66 35 eb 1d da |._,.g.w<0..f5...| +00000040 6e dd 30 ff 82 05 5f f1 cd e7 15 03 01 00 20 6c |n.0..._....... l| +00000050 47 82 5e 90 5b 84 15 78 05 bd 48 63 d5 46 2f 7e |G.^.[..x..Hc.F/~| +00000060 83 49 ce 3c 0f 04 92 52 5b e7 d5 cf 2c bf 65 |.I.<...R[...,.e| diff --git a/libgo/go/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial b/libgo/go/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial new file mode 100644 index 00000000000..29964f0d407 --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Client-TLSv12-ExportKeyingMaterial @@ -0,0 +1,84 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 95 01 00 00 91 03 03 00 00 00 00 00 |................| +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 00 00 2c cc a8 |.............,..| +00000030 cc a9 c0 2f c0 2b c0 30 c0 2c c0 27 c0 13 c0 23 |.../.+.0.,.'...#| +00000040 c0 09 c0 14 c0 0a 00 9c 00 9d 00 3c 00 2f 00 35 |...........<./.5| +00000050 c0 12 00 0a 00 05 c0 11 c0 07 01 00 00 3c 00 05 |.............<..| +00000060 00 05 01 00 00 00 00 00 0a 00 0a 00 08 00 1d 00 |................| +00000070 17 00 18 00 19 00 0b 00 02 01 00 00 0d 00 12 00 |................| +00000080 10 04 01 04 03 05 01 05 03 06 01 06 03 02 01 02 |................| +00000090 03 ff 01 00 01 00 00 12 00 00 |..........| +>>> Flow 2 (server to client) +00000000 16 03 03 00 59 02 00 00 55 03 03 fc 37 e8 a4 e3 |....Y...U...7...| +00000010 5d da a5 95 0b fb e0 c3 d9 78 8b 91 bd 5c 1c b1 |]........x...\..| +00000020 c6 8d 69 62 f9 c6 0f 12 da 46 ba 20 34 a3 22 f2 |..ib.....F. 4.".| +00000030 a9 f7 da 3a c4 5f 6f f7 4b be df 03 e5 b6 d0 ff |...:._o.K.......| +00000040 ca 54 68 59 57 53 63 a5 2f 91 1d 1e cc a8 00 00 |.ThYWSc./.......| +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..............| +00000080 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 0d 01 |?.[..0...*.H....| +00000090 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 0a 13 |....0.1.0...U...| +000000a0 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 47 6f |.Go1.0...U....Go| +000000b0 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 31 30 | Root0...1601010| +000000c0 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 30 30 |00000Z..25010100| +000000d0 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 04 0a |0000Z0.1.0...U..| +000000e0 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 02 47 |..Go1.0...U....G| +000000f0 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01 |o0..0...*.H.....| +00000100 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 db 46 |.......0.......F| +00000110 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 |}...'.H..(!.~...| +00000120 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 5b c2 |]..RE.z6G....B[.| +00000130 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 |....y.@.Om..+...| +00000140 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b |..g....."8.J.ts+| +00000150 c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c |.4......t{.X.la<| +00000160 c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d |..A..++$#w[.;.u]| +00000170 ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b |. T..c...$....P.| +00000180 aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 |...C...ub...R...| +00000190 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 1d 0f |......0..0...U..| +000001a0 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 1d 25 |.........0...U.%| +000001b0 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 06 08 |..0...+.........| +000001c0 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d 13 01 |+.......0...U...| +000001d0 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 12 04 |....0.0...U.....| +000001e0 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f |.....CC>I..m....| +000001f0 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 48 13 |`0...U.#..0...H.| +00000200 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 |IM.~.1......n{0.| +00000210 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 6d 70 |..U....0...examp| +00000220 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 |le.golang0...*.H| +00000230 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 cc 40 |.............0.@| +00000240 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 a9 58 |+[P.a...SX...(.X| +00000250 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d |..8....1Z..f=C.-| +00000260 d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc cf 9c |...... d8.$:....| +00000270 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd 13 c3 |}.@ ._...a..v...| +00000280 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb b3 43 |...\.....l..s..C| +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 cc e9 71 f5 36 52 5a |........ ..q.6RZ| +000002d0 d8 19 ce e4 0d 41 8d a6 9b f3 19 56 8d 81 fe 84 |.....A.....V....| +000002e0 71 2f d7 fb e7 86 23 4c 04 04 01 00 80 90 da 29 |q/....#L.......)| +000002f0 79 18 70 e8 81 66 83 70 97 f1 d1 5f dc 1d a2 0a |y.p..f.p..._....| +00000300 94 d8 e8 b8 32 4f 03 34 0b af e8 2d 94 b2 eb 30 |....2O.4...-...0| +00000310 57 b5 a5 92 9e 9a df a6 bc 3e 25 0e 18 cb ea 84 |W........>%.....| +00000320 34 89 08 8a d4 be 16 a3 5d 3a 7d 32 10 9b 41 1c |4.......]:}2..A.| +00000330 2a 1e 05 68 5f fa d9 56 30 b6 44 08 b0 a5 25 5a |*..h_..V0.D...%Z| +00000340 c3 60 c0 9a 98 fd 48 5f a4 18 d0 15 0f fb b3 ea |.`....H_........| +00000350 b9 c4 e3 c6 0c 27 51 64 01 de 65 78 c7 a0 57 df |.....'Qd..ex..W.| +00000360 9b de 2f 74 bc 72 e5 e0 57 7c 59 e6 ae 16 03 03 |../t.r..W|Y.....| +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 92 0a 4e aa 2d b3 9b c8 b9 80 28 |.... ..N.-.....(| +00000040 f3 22 e2 57 15 ff a1 9a 33 9b e8 4c 5c dc f4 29 |.".W....3..L\..)| +00000050 7d 25 d7 df bc |}%...| +>>> Flow 4 (server to client) +00000000 14 03 03 00 01 01 16 03 03 00 20 91 85 06 0e 00 |.......... .....| +00000010 ad 96 2e 1c a5 4d f7 63 f9 84 1c 6e da 54 0b e0 |.....M.c...n.T..| +00000020 44 37 6a 90 4c fd f5 e8 45 1d ce |D7j.L...E..| +>>> Flow 5 (client to server) +00000000 17 03 03 00 16 4c e8 8a e0 a6 95 f3 df 37 8a 2d |.....L.......7.-| +00000010 4f 11 ce a6 53 16 2c b0 bb c5 7f 15 03 03 00 12 |O...S.,.........| +00000020 4e 91 d8 67 c5 16 d2 4e cc b8 0a 00 76 91 68 7a |N..g...N....v.hz| +00000030 85 2e |..| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial b/libgo/go/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial new file mode 100644 index 00000000000..84e0e37005f --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv10-ExportKeyingMaterial @@ -0,0 +1,92 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 61 01 00 00 5d 03 01 f4 ec 99 73 ec |....a...].....s.| +00000010 36 30 c7 0b 26 33 a2 c4 26 8e 9f 04 f7 5b e7 4f |60..&3..&....[.O| +00000020 86 85 14 bf f7 49 96 a4 ae c9 1d 00 00 12 c0 0a |.....I..........| +00000030 c0 14 00 39 c0 09 c0 13 00 33 00 35 00 2f 00 ff |...9.....3.5./..| +00000040 01 00 00 22 00 0b 00 04 03 00 01 02 00 0a 00 0a |..."............| +00000050 00 08 00 1d 00 17 00 19 00 18 00 23 00 00 00 16 |...........#....| +00000060 00 00 00 17 00 00 |......| +>>> Flow 2 (server to client) +00000000 16 03 01 00 35 02 00 00 31 03 01 00 00 00 00 00 |....5...1.......| +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 00 c0 14 00 00 |................| +00000030 09 00 23 00 00 ff 01 00 01 00 16 03 01 02 59 0b |..#...........Y.| +00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| +00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| +00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........| +00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1| +00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| +00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000| +000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| +000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go| +000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..| +000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........| +000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...| +000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R| +00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....| +00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.| +00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..| +00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.| +00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.| +00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C| +00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......| +00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......| +00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.| +00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...| +000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......| +000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........| +000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..| +000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~| +000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.| +000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g| +00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....| +00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.| +00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.| +00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....| +00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ | +00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\| +00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| +00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| +00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| +00000290 84 5c 21 d3 3b e9 fa e7 16 03 01 00 aa 0c 00 00 |.\!.;...........| +000002a0 a6 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 28 da |.... /.}.G.bC.(.| +000002b0 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........| +000002c0 5f 58 cb 3b 74 00 80 8e fe 28 f2 06 d8 b9 d6 74 |_X.;t....(.....t| +000002d0 72 34 dc fa 00 38 56 1a fc a1 68 e8 ca 8f 7a 61 |r4...8V...h...za| +000002e0 92 e2 2a 63 ce 4d 96 c6 bb 84 82 41 2d 97 35 13 |..*c.M.....A-.5.| +000002f0 e1 ff 4c ec f2 e6 62 16 15 35 da 8a 57 55 cb 28 |..L...b..5..WU.(| +00000300 26 35 e6 86 00 b0 92 44 b7 40 7b 6a c4 b0 b8 10 |&5.....D.@{j....| +00000310 b7 16 97 a7 26 eb 1e 0b 99 b3 22 4a 6b 7f 0b 69 |....&....."Jk..i| +00000320 0d 21 1e 33 6d fd 78 b5 62 68 53 db 62 69 ba b4 |.!.3m.x.bhS.bi..| +00000330 bc 74 b3 d4 ce a2 41 d7 ba 62 aa cc b2 39 65 86 |.t....A..b...9e.| +00000340 5f 00 68 e2 16 a5 13 16 03 01 00 04 0e 00 00 00 |_.h.............| +>>> Flow 3 (client to server) +00000000 16 03 01 00 25 10 00 00 21 20 81 08 e4 37 1d 03 |....%...! ...7..| +00000010 87 5a 00 68 ae 49 76 08 4a e2 20 82 0b e5 7c 3e |.Z.h.Iv.J. ...|>| +00000020 90 49 9b c3 b9 c7 c9 3c 29 24 14 03 01 00 01 01 |.I.....<)$......| +00000030 16 03 01 00 30 33 07 d5 08 ca ae f9 70 50 93 0a |....03......pP..| +00000040 55 2e e0 df 1d 88 ae 1e 06 17 47 64 a3 52 36 37 |U.........Gd.R67| +00000050 d5 ca f1 b1 d2 76 7b f8 89 59 13 e9 ab b1 cb dc |.....v{..Y......| +00000060 1f a8 89 f4 2f |..../| +>>> Flow 4 (server to client) +00000000 16 03 01 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP| +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 61 a4 a1 9c 14 de f8 59 c8 c7 f0 10 |m...a......Y....| +00000040 08 fe c9 37 29 ed 47 05 d2 bd a8 4c 05 b9 8c f8 |...7).G....L....| +00000050 b5 4d e4 a6 30 0f 49 4a b1 73 1f 89 73 c8 bb 36 |.M..0.IJ.s..s..6| +00000060 14 9d d2 95 70 33 94 fb 82 e6 fe 3e 64 8c 9d e8 |....p3.....>d...| +00000070 e3 e5 93 3d fe 4e 23 a3 97 8a a3 91 80 c9 00 01 |...=.N#.........| +00000080 a6 f0 47 cf 11 a6 90 14 03 01 00 01 01 16 03 01 |..G.............| +00000090 00 30 1f 70 17 a1 30 82 5a 32 e7 aa a1 7f 1b f6 |.0.p..0.Z2......| +000000a0 d8 aa 6a 51 64 1b 4a f1 94 12 08 2f 5d 95 fe 83 |..jQd.J..../]...| +000000b0 52 c8 3b d4 58 73 50 19 b8 08 61 b3 3a 5d f6 d3 |R.;.XsP...a.:]..| +000000c0 67 e6 17 03 01 00 20 bd 79 44 08 9d 86 cf 5e e9 |g..... .yD....^.| +000000d0 e4 3c 80 ed b7 18 10 07 0f 42 85 ca a4 51 fd 9b |.<.......B...Q..| +000000e0 38 3e 04 7e 72 6e 80 17 03 01 00 30 2c 46 c2 71 |8>.~rn.....0,F.q| +000000f0 4a 83 46 eb 63 87 f5 83 b4 72 70 4f a3 59 b3 ff |J.F.c....rpO.Y..| +00000100 3c 00 74 12 db 33 51 4c 7c e0 c1 27 44 20 68 25 |<.t..3QL|..'D h%| +00000110 95 f1 37 2a 24 f1 85 a3 5a e4 50 fe 15 03 01 00 |..7*$...Z.P.....| +00000120 20 72 01 cc 74 d5 b4 6b 05 ce de f0 b4 fe 4f 6b | r..t..k......Ok| +00000130 a8 8f ad 5a c2 7d 40 65 d6 a2 57 52 b8 8a c5 4f |...Z.}@e..WR...O| +00000140 d9 |.| diff --git a/libgo/go/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial b/libgo/go/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial new file mode 100644 index 00000000000..6415c42928d --- /dev/null +++ b/libgo/go/crypto/tls/testdata/Server-TLSv12-ExportKeyingMaterial @@ -0,0 +1,92 @@ +>>> Flow 1 (client to server) +00000000 16 03 01 00 ab 01 00 00 a7 03 03 7a 49 9d 20 62 |...........zI. b| +00000010 45 8d 0c 1e 8e eb b1 5e 73 62 6d 48 61 31 cb 1a |E......^sbmHa1..| +00000020 89 b2 68 1b 2c cb 35 87 2a 17 fb 00 00 38 c0 2c |..h.,.5.*....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 46 00 0b 00 04 03 00 |.5./.....F......| +00000070 01 02 00 0a 00 0a 00 08 00 1d 00 17 00 19 00 18 |................| +00000080 00 23 00 00 00 16 00 00 00 17 00 00 00 0d 00 20 |.#............. | +00000090 00 1e 06 01 06 02 06 03 05 01 05 02 05 03 04 01 |................| +000000a0 04 02 04 03 03 01 03 02 03 03 02 01 02 02 02 03 |................| +>>> Flow 2 (server to client) +00000000 16 03 03 00 35 02 00 00 31 03 03 00 00 00 00 00 |....5...1.......| +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 00 c0 30 00 00 |.............0..| +00000030 09 00 23 00 00 ff 01 00 01 00 16 03 03 02 59 0b |..#...........Y.| +00000040 00 02 55 00 02 52 00 02 4f 30 82 02 4b 30 82 01 |..U..R..O0..K0..| +00000050 b4 a0 03 02 01 02 02 09 00 e8 f0 9d 3f e2 5b ea |............?.[.| +00000060 a6 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 |.0...*.H........| +00000070 30 1f 31 0b 30 09 06 03 55 04 0a 13 02 47 6f 31 |0.1.0...U....Go1| +00000080 10 30 0e 06 03 55 04 03 13 07 47 6f 20 52 6f 6f |.0...U....Go Roo| +00000090 74 30 1e 17 0d 31 36 30 31 30 31 30 30 30 30 30 |t0...16010100000| +000000a0 30 5a 17 0d 32 35 30 31 30 31 30 30 30 30 30 30 |0Z..250101000000| +000000b0 5a 30 1a 31 0b 30 09 06 03 55 04 0a 13 02 47 6f |Z0.1.0...U....Go| +000000c0 31 0b 30 09 06 03 55 04 03 13 02 47 6f 30 81 9f |1.0...U....Go0..| +000000d0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01 05 00 03 |0...*.H.........| +000000e0 81 8d 00 30 81 89 02 81 81 00 db 46 7d 93 2e 12 |...0.......F}...| +000000f0 27 06 48 bc 06 28 21 ab 7e c4 b6 a2 5d fe 1e 52 |'.H..(!.~...]..R| +00000100 45 88 7a 36 47 a5 08 0d 92 42 5b c2 81 c0 be 97 |E.z6G....B[.....| +00000110 79 98 40 fb 4f 6d 14 fd 2b 13 8b c2 a5 2e 67 d8 |y.@.Om..+.....g.| +00000120 d4 09 9e d6 22 38 b7 4a 0b 74 73 2b c2 34 f1 d1 |...."8.J.ts+.4..| +00000130 93 e5 96 d9 74 7b f3 58 9f 6c 61 3c c0 b0 41 d4 |....t{.X.la<..A.| +00000140 d9 2b 2b 24 23 77 5b 1c 3b bd 75 5d ce 20 54 cf |.++$#w[.;.u]. T.| +00000150 a1 63 87 1d 1e 24 c4 f3 1d 1a 50 8b aa b6 14 43 |.c...$....P....C| +00000160 ed 97 a7 75 62 f4 14 c8 52 d7 02 03 01 00 01 a3 |...ub...R.......| +00000170 81 93 30 81 90 30 0e 06 03 55 1d 0f 01 01 ff 04 |..0..0...U......| +00000180 04 03 02 05 a0 30 1d 06 03 55 1d 25 04 16 30 14 |.....0...U.%..0.| +00000190 06 08 2b 06 01 05 05 07 03 01 06 08 2b 06 01 05 |..+.........+...| +000001a0 05 07 03 02 30 0c 06 03 55 1d 13 01 01 ff 04 02 |....0...U.......| +000001b0 30 00 30 19 06 03 55 1d 0e 04 12 04 10 9f 91 16 |0.0...U.........| +000001c0 1f 43 43 3e 49 a6 de 6d b6 80 d7 9f 60 30 1b 06 |.CC>I..m....`0..| +000001d0 03 55 1d 23 04 14 30 12 80 10 48 13 49 4d 13 7e |.U.#..0...H.IM.~| +000001e0 16 31 bb a3 01 d5 ac ab 6e 7b 30 19 06 03 55 1d |.1......n{0...U.| +000001f0 11 04 12 30 10 82 0e 65 78 61 6d 70 6c 65 2e 67 |...0...example.g| +00000200 6f 6c 61 6e 67 30 0d 06 09 2a 86 48 86 f7 0d 01 |olang0...*.H....| +00000210 01 0b 05 00 03 81 81 00 9d 30 cc 40 2b 5b 50 a0 |.........0.@+[P.| +00000220 61 cb ba e5 53 58 e1 ed 83 28 a9 58 1a a9 38 a4 |a...SX...(.X..8.| +00000230 95 a1 ac 31 5a 1a 84 66 3d 43 d3 2d d9 0b f2 97 |...1Z..f=C.-....| +00000240 df d3 20 64 38 92 24 3a 00 bc cf 9c 7d b7 40 20 |.. d8.$:....}.@ | +00000250 01 5f aa d3 16 61 09 a2 76 fd 13 c3 cc e1 0c 5c |._...a..v......\| +00000260 ee b1 87 82 f1 6c 04 ed 73 bb b3 43 77 8d 0c 1c |.....l..s..Cw...| +00000270 f1 0f a1 d8 40 83 61 c9 4c 72 2b 9d ae db 46 06 |....@.a.Lr+...F.| +00000280 06 4d f4 c1 b3 3e c0 d1 bd 42 d4 db fe 3d 13 60 |.M...>...B...=.`| +00000290 84 5c 21 d3 3b e9 fa e7 16 03 03 00 ac 0c 00 00 |.\!.;...........| +000002a0 a8 03 00 1d 20 2f e5 7d a3 47 cd 62 43 15 28 da |.... /.}.G.bC.(.| +000002b0 ac 5f bb 29 07 30 ff f6 84 af c4 cf c2 ed 90 99 |._.).0..........| +000002c0 5f 58 cb 3b 74 06 01 00 80 7f ee dd 6b 38 23 29 |_X.;t.......k8#)| +000002d0 56 ff d2 c2 08 86 52 b6 e3 8a d5 fe 47 79 5e ef |V.....R.....Gy^.| +000002e0 99 7a 0b d7 44 84 b9 2f 7a 2c 64 4f b3 7c aa 44 |.z..D../z,dO.|.D| +000002f0 aa 38 5d 1b 69 16 9f f2 7d f8 24 43 47 ad 31 bc |.8].i...}.$CG.1.| +00000300 f5 3d b8 c8 33 6e 3f 6f 2b ea 19 a2 30 32 2b 2a |.=..3n?o+...02+*| +00000310 81 64 3c ee ed 78 4c fa 80 fd e7 5f ef 85 98 d4 |.d<..xL...._....| +00000320 48 06 b8 f5 5e 1e e6 f3 42 a8 2f 99 5f ea b3 ba |H...^...B./._...| +00000330 8e a8 31 99 85 f2 46 11 a3 d2 c6 81 4b f1 22 7d |..1...F.....K."}| +00000340 d7 45 04 f1 a6 d6 7e 8f 9d 16 03 03 00 04 0e 00 |.E....~.........| +00000350 00 00 |..| +>>> Flow 3 (client to server) +00000000 16 03 03 00 25 10 00 00 21 20 22 e7 e7 61 a9 27 |....%...! "..a.'| +00000010 7b 93 d1 42 76 dd 16 32 e8 92 37 37 2f fd 0d 92 |{..Bv..2..77/...| +00000020 1f 8e b7 c5 69 40 d3 1a 7d 06 14 03 03 00 01 01 |....i@..}.......| +00000030 16 03 03 00 28 4e 7f b2 a2 20 5d cf a1 5a de 42 |....(N... ]..Z.B| +00000040 c5 72 c3 ef c3 23 a7 2c f3 5b 3d a4 81 21 ac db |.r...#.,.[=..!..| +00000050 44 1c f3 a1 83 aa a1 b7 85 9a c7 23 03 |D..........#.| +>>> Flow 4 (server to client) +00000000 16 03 03 00 82 04 00 00 7e 00 00 00 00 00 78 50 |........~.....xP| +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 ec 80 83 61 3f 55 e3 9d ab 39 87 5b d0 ba 44 |o...a?U...9.[..D| +00000040 07 91 a8 d0 37 8a 7e 51 0d 00 97 ec 1b 61 f3 3b |....7.~Q.....a.;| +00000050 9f 29 24 d5 98 f7 4d 3b 80 ef 2f 4d aa 02 98 93 |.)$...M;../M....| +00000060 81 03 87 d8 06 33 94 f5 ed 5d cc 8f 57 97 70 26 |.....3...]..W.p&| +00000070 00 dc 0d d2 96 16 a2 6d fc be 8d 4b fa 5f b3 04 |.......m...K._..| +00000080 ce bb 48 ee c0 75 23 14 03 03 00 01 01 16 03 03 |..H..u#.........| +00000090 00 28 00 00 00 00 00 00 00 00 3a 69 e0 40 e2 d1 |.(........:i.@..| +000000a0 a6 96 33 0f b3 58 5a dc 41 ea d1 80 44 66 9f 2e |..3..XZ.A...Df..| +000000b0 00 e4 9e 10 13 56 b4 1b c9 42 17 03 03 00 25 00 |.....V...B....%.| +000000c0 00 00 00 00 00 00 01 88 f3 d9 5b ed 6b 3c 70 0c |..........[.k 0 { t.Errorf("#%d: unexpectedly succeeded against OpenSSL", i) @@ -1912,7 +1993,7 @@ func TestConstraintCases(t *testing.T) { if _, ok := err.(*exec.ExitError); !ok { t.Errorf("#%d: OpenSSL failed to run: %s", i, err) } else if len(test.expectedError) == 0 { - t.Errorf("#%d: OpenSSL unexpectedly failed: %q", i, output) + t.Errorf("#%d: OpenSSL unexpectedly failed: %v", i, output) if debugOpenSSLFailure { return } @@ -1920,6 +2001,7 @@ func TestConstraintCases(t *testing.T) { } } + ignoreCN = test.ignoreCN verifyOpts := VerifyOptions{ Roots: rootPool, Intermediates: intermediatePool, @@ -1949,7 +2031,7 @@ func TestConstraintCases(t *testing.T) { certAsPEM := func(cert *Certificate) string { var buf bytes.Buffer pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) - return string(buf.Bytes()) + return buf.String() } t.Errorf("#%d: root:\n%s", i, certAsPEM(rootPool.certs[0])) t.Errorf("#%d: leaf:\n%s", i, certAsPEM(leafCert)) @@ -2012,7 +2094,7 @@ func testChainAgainstOpenSSL(leaf *Certificate, intermediates, roots *CertPool) cmd.Stderr = &output err := cmd.Run() - return string(output.Bytes()), err + return output.String(), err } var rfc2821Tests = []struct { diff --git a/libgo/go/crypto/x509/pkcs8.go b/libgo/go/crypto/x509/pkcs8.go index eb051b6e114..fb1340c6df7 100644 --- a/libgo/go/crypto/x509/pkcs8.go +++ b/libgo/go/crypto/x509/pkcs8.go @@ -56,7 +56,7 @@ func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { } // MarshalPKCS8PrivateKey converts a private key to PKCS#8 encoded form. -// The following key types are supported: *rsa.PrivateKey, *ecdsa.PublicKey. +// The following key types are supported: *rsa.PrivateKey, *ecdsa.PrivateKey. // Unsupported key types result in an error. // // See RFC 5208. diff --git a/libgo/go/crypto/x509/pkix/pkix.go b/libgo/go/crypto/x509/pkix/pkix.go index 7b32220b74e..3cc4d587e36 100644 --- a/libgo/go/crypto/x509/pkix/pkix.go +++ b/libgo/go/crypto/x509/pkix/pkix.go @@ -95,7 +95,7 @@ func (r RDNSequence) String() string { type RelativeDistinguishedNameSET []AttributeTypeAndValue // AttributeTypeAndValue mirrors the ASN.1 structure of the same name in -// http://tools.ietf.org/html/rfc5280#section-4.1.2.4 +// https://tools.ietf.org/html/rfc5280#section-4.1.2.4 type AttributeTypeAndValue struct { Type asn1.ObjectIdentifier Value interface{} diff --git a/libgo/go/crypto/x509/root.go b/libgo/go/crypto/x509/root.go index 787d955be47..240296247df 100644 --- a/libgo/go/crypto/x509/root.go +++ b/libgo/go/crypto/x509/root.go @@ -19,4 +19,7 @@ func systemRootsPool() *CertPool { func initSystemRoots() { systemRoots, systemRootsErr = loadSystemRoots() + if systemRootsErr != nil { + systemRoots = nil + } } diff --git a/libgo/go/crypto/x509/root_cgo_darwin.go b/libgo/go/crypto/x509/root_cgo_darwin.go index 80cd2501c43..a02ac3cfe83 100644 --- a/libgo/go/crypto/x509/root_cgo_darwin.go +++ b/libgo/go/crypto/x509/root_cgo_darwin.go @@ -7,7 +7,7 @@ package x509 /* -#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1080 +#cgo CFLAGS: -mmacosx-version-min=10.10 -D__MAC_OS_X_VERSION_MAX_ALLOWED=101300 #cgo LDFLAGS: -framework CoreFoundation -framework Security #include @@ -16,59 +16,6 @@ package x509 #include #include -// FetchPEMRoots_MountainLion is the version of FetchPEMRoots from Go 1.6 -// which still works on OS X 10.8 (Mountain Lion). -// It lacks support for admin & user cert domains. -// See golang.org/issue/16473 -int FetchPEMRoots_MountainLion(CFDataRef *pemRoots) { - if (pemRoots == NULL) { - return -1; - } - CFArrayRef certs = NULL; - OSStatus err = SecTrustCopyAnchorCertificates(&certs); - if (err != noErr) { - return -1; - } - CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0); - int i, ncerts = CFArrayGetCount(certs); - for (i = 0; i < ncerts; i++) { - CFDataRef data = NULL; - SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i); - if (cert == NULL) { - continue; - } - // Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport. - // Once we support weak imports via cgo we should prefer that, and fall back to this - // for older systems. - err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data); - if (err != noErr) { - continue; - } - if (data != NULL) { - CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data)); - CFRelease(data); - } - } - CFRelease(certs); - *pemRoots = combinedData; - return 0; -} - -// useOldCode reports whether the running machine is OS X 10.8 Mountain Lion -// or older. We only support Mountain Lion and higher, but we'll at least try our -// best on older machines and continue to use the old code path. -// -// See golang.org/issue/16473 -int useOldCode() { - char str[256]; - size_t size = sizeof(str); - memset(str, 0, size); - sysctlbyname("kern.osrelease", str, &size, NULL, 0); - // OS X 10.8 is osrelease "12.*", 10.7 is 11.*, 10.6 is 10.*. - // We never supported things before that. - return memcmp(str, "12.", 3) == 0 || memcmp(str, "11.", 3) == 0 || memcmp(str, "10.", 3) == 0; -} - // FetchPEMRoots fetches the system's list of trusted X.509 root certificates. // // On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root @@ -78,9 +25,7 @@ int useOldCode() { // Note: The CFDataRef returned in pemRoots and untrustedPemRoots must // be released (using CFRelease) after we've consumed its content. int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) { - if (useOldCode()) { - return FetchPEMRoots_MountainLion(pemRoots); - } + int i; // Get certificates from all domains, not just System, this lets // the user add CAs to their "login" keychain, and Admins to add @@ -101,7 +46,8 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) { CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0); CFMutableDataRef combinedUntrustedData = CFDataCreateMutable(kCFAllocatorDefault, 0); - for (int i = 0; i < numDomains; i++) { + for (i = 0; i < numDomains; i++) { + int j; CFArrayRef certs = NULL; OSStatus err = SecTrustSettingsCopyCertificates(domains[i], &certs); if (err != noErr) { @@ -109,7 +55,7 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) { } CFIndex numCerts = CFArrayGetCount(certs); - for (int j = 0; j < numCerts; j++) { + for (j = 0; j < numCerts; j++) { CFDataRef data = NULL; CFErrorRef errRef = NULL; CFArrayRef trustSettings = NULL; @@ -124,6 +70,9 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) { if (i == 0) { trustAsRoot = 1; } else { + int k; + CFIndex m; + // Certs found in the system domain are always trusted. If the user // configures "Never Trust" on such a cert, it will also be found in the // admin or user domain, causing it to be added to untrustedPemRoots. The @@ -133,7 +82,7 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) { // SecTrustServer.c, "user trust settings overrule admin trust settings", // so take the last trust settings array we find. // Skip the system domain since it is always trusted. - for (int k = i; k < numDomains; k++) { + for (k = i; k < numDomains; k++) { CFArrayRef domainTrustSettings = NULL; err = SecTrustSettingsCopyTrustSettings(cert, domains[k], &domainTrustSettings); if (err == errSecSuccess && domainTrustSettings != NULL) { @@ -147,9 +96,9 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) { // "this certificate must be verified to a known trusted certificate"; aka not a root. continue; } - for (CFIndex k = 0; k < CFArrayGetCount(trustSettings); k++) { + for (m = 0; m < CFArrayGetCount(trustSettings); m++) { CFNumberRef cfNum; - CFDictionaryRef tSetting = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, k); + CFDictionaryRef tSetting = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, m); if (CFDictionaryGetValueIfPresent(tSetting, policy, (const void**)&cfNum)){ SInt32 result = 0; CFNumberGetValue(cfNum, kCFNumberSInt32Type, &result); @@ -187,10 +136,7 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) { } } - // Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport. - // Once we support weak imports via cgo we should prefer that, and fall back to this - // for older systems. - err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data); + err = SecItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data); if (err != noErr) { continue; } diff --git a/libgo/go/crypto/x509/root_darwin.go b/libgo/go/crypto/x509/root_darwin.go index bc35a1cf212..9d7b3a6ffb6 100644 --- a/libgo/go/crypto/x509/root_darwin.go +++ b/libgo/go/crypto/x509/root_darwin.go @@ -181,12 +181,12 @@ func verifyCertWithSystem(block *pem.Block, cert *Certificate) bool { } if err := cmd.Run(); err != nil { if debugExecDarwinRoots { - println(fmt.Sprintf("crypto/x509: verify-cert rejected %s: %q", cert.Subject.CommonName, bytes.TrimSpace(stderr.Bytes()))) + println(fmt.Sprintf("crypto/x509: verify-cert rejected %s: %q", cert.Subject, bytes.TrimSpace(stderr.Bytes()))) } return false } if debugExecDarwinRoots { - println(fmt.Sprintf("crypto/x509: verify-cert approved %s", cert.Subject.CommonName)) + println(fmt.Sprintf("crypto/x509: verify-cert approved %s", cert.Subject)) } return true } diff --git a/libgo/go/crypto/x509/root_js.go b/libgo/go/crypto/x509/root_js.go new file mode 100644 index 00000000000..70abb73f99c --- /dev/null +++ b/libgo/go/crypto/x509/root_js.go @@ -0,0 +1,10 @@ +// 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 js,wasm + +package x509 + +// Possible certificate files; stop after finding one. +var certFiles = []string{} diff --git a/libgo/go/crypto/x509/root_plan9.go b/libgo/go/crypto/x509/root_plan9.go index ebeb7dfccd8..09f0e230339 100644 --- a/libgo/go/crypto/x509/root_plan9.go +++ b/libgo/go/crypto/x509/root_plan9.go @@ -33,5 +33,8 @@ func loadSystemRoots() (*CertPool, error) { bestErr = err } } + if bestErr == nil { + return roots, nil + } return nil, bestErr } diff --git a/libgo/go/crypto/x509/root_unix.go b/libgo/go/crypto/x509/root_unix.go index 0547460437b..48de50b4ea6 100644 --- a/libgo/go/crypto/x509/root_unix.go +++ b/libgo/go/crypto/x509/root_unix.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. -// +build aix dragonfly freebsd linux nacl netbsd openbsd solaris +// +build aix dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris package x509 @@ -81,7 +81,7 @@ func loadSystemRoots() (*CertPool, error) { } } - if len(roots.certs) > 0 { + if len(roots.certs) > 0 || firstErr == nil { return roots, nil } diff --git a/libgo/go/crypto/x509/root_unix_test.go b/libgo/go/crypto/x509/root_unix_test.go index 03f935d4e82..9e220192b9f 100644 --- a/libgo/go/crypto/x509/root_unix_test.go +++ b/libgo/go/crypto/x509/root_unix_test.go @@ -103,10 +103,6 @@ func TestEnvVars(t *testing.T) { } if r == nil { - if tc.cns == nil { - // Expected nil - return - } t.Fatal("nil roots") } diff --git a/libgo/go/crypto/x509/root_windows.go b/libgo/go/crypto/x509/root_windows.go index 3621a93abac..74d395df707 100644 --- a/libgo/go/crypto/x509/root_windows.go +++ b/libgo/go/crypto/x509/root_windows.go @@ -95,12 +95,6 @@ func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) e return nil } -type _CertChainPolicyPara struct { - Size uint32 - Flags uint32 - ExtraPolicyPara unsafe.Pointer -} - // checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for // use as a certificate chain for a SSL/TLS server. func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error { @@ -114,13 +108,13 @@ func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContex } sslPara.Size = uint32(unsafe.Sizeof(*sslPara)) - para := &_CertChainPolicyPara{ - ExtraPolicyPara: unsafe.Pointer(sslPara), + para := &syscall.CertChainPolicyPara{ + ExtraPolicyPara: (syscall.Pointer)(unsafe.Pointer(sslPara)), } para.Size = uint32(unsafe.Sizeof(*para)) status := syscall.CertChainPolicyStatus{} - err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, (*syscall.CertChainPolicyPara)(unsafe.Pointer(para)), &status) + err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status) if err != nil { return err } diff --git a/libgo/go/crypto/x509/sha2_windows_test.go b/libgo/go/crypto/x509/sha2_windows_test.go deleted file mode 100644 index 79dc685c5b5..00000000000 --- a/libgo/go/crypto/x509/sha2_windows_test.go +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -package x509 - -import "syscall" - -func init() { - v, err := syscall.GetVersion() - if err != nil { - return - } - if major := byte(v); major < 6 { - // Windows XP SP2 and Windows 2003 do not support SHA2. - // http://blogs.technet.com/b/pki/archive/2010/09/30/sha2-and-windows.aspx - supportSHA2 = false - } -} diff --git a/libgo/go/crypto/x509/verify.go b/libgo/go/crypto/x509/verify.go index 60e415b7ec2..210db4c1d0e 100644 --- a/libgo/go/crypto/x509/verify.go +++ b/libgo/go/crypto/x509/verify.go @@ -6,19 +6,21 @@ package x509 import ( "bytes" - "encoding/asn1" "errors" "fmt" "net" "net/url" + "os" "reflect" "runtime" - "strconv" "strings" "time" "unicode/utf8" ) +// ignoreCN disables interpreting Common Name as a hostname. See issue 24151. +var ignoreCN = strings.Contains(os.Getenv("GODEBUG"), "x509ignoreCN=1") + type InvalidReason int const ( @@ -43,13 +45,18 @@ const ( NameMismatch // NameConstraintsWithoutSANs results when a leaf certificate doesn't // contain a Subject Alternative Name extension, but a CA certificate - // contains name constraints. + // contains name constraints, and the Common Name can be interpreted as + // a hostname. + // + // You can avoid this error by setting the experimental GODEBUG environment + // variable to "x509ignoreCN=1", disabling Common Name matching entirely. + // This behavior might become the default in the future. NameConstraintsWithoutSANs // UnconstrainedName results when a CA certificate contains permitted // name constraints, but leaf certificate contains a name of an // unsupported or unconstrained type. UnconstrainedName - // TooManyConstraints results when the number of comparision operations + // TooManyConstraints results when the number of comparison operations // needed to check a certificate exceeds the limit set by // VerifyOptions.MaxConstraintComparisions. This limit exists to // prevent pathological certificates can consuming excessive amounts of @@ -102,6 +109,12 @@ type HostnameError struct { func (h HostnameError) Error() string { c := h.Certificate + if !c.hasSANExtension() && !validHostname(c.Subject.CommonName) && + matchHostnames(toLowerCaseASCII(c.Subject.CommonName), toLowerCaseASCII(h.Host)) { + // 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 + } + var valid string if ip := net.ParseIP(h.Host); ip != nil { // Trying to validate an IP @@ -115,10 +128,10 @@ func (h HostnameError) Error() string { valid += san.String() } } else { - if c.hasSANExtension() { - valid = strings.Join(c.DNSNames, ", ") - } else { + if c.commonNameAsHostname() { valid = c.Subject.CommonName + } else { + valid = strings.Join(c.DNSNames, ", ") } } @@ -189,7 +202,7 @@ type VerifyOptions struct { KeyUsages []ExtKeyUsage // MaxConstraintComparisions is the maximum number of comparisons to // perform when checking a given certificate's name constraints. If - // zero, a sensible default is used. This limit prevents pathalogical + // zero, a sensible default is used. This limit prevents pathological // certificates from consuming excessive amounts of CPU time when // validating. MaxConstraintComparisions int @@ -583,17 +596,16 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V leaf = currentChain[0] } - if (certType == intermediateCertificate || certType == rootCertificate) && c.hasNameConstraints() { - sanExtension, ok := leaf.getSANExtension() - if !ok { - // This is the deprecated, legacy case of depending on - // the CN as a hostname. Chains modern enough to be - // using name constraints should not be depending on - // CNs. - return CertificateInvalidError{c, NameConstraintsWithoutSANs, ""} - } - - err := forEachSAN(sanExtension, func(tag int, data []byte) error { + 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() { + err := forEachSAN(leaf.getSANExtension(), func(tag int, data []byte) error { switch tag { case nameTypeEmail: name := string(data) @@ -692,18 +704,6 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V return nil } -// formatOID formats an ASN.1 OBJECT IDENTIFER in the common, dotted style. -func formatOID(oid asn1.ObjectIdentifier) string { - ret := "" - for i, v := range oid { - if i > 0 { - ret += "." - } - ret += strconv.Itoa(v) - } - return ret -} - // Verify attempts to verify c by building one or more chains from c to a // certificate in opts.Roots, using certificates in opts.Intermediates if // needed. If successful, it returns one or more chains where the first @@ -860,6 +860,64 @@ nextIntermediate: return } +// validHostname returns whether host is a valid hostname that can be matched or +// matched against according to RFC 6125 2.2, with some leniency to accomodate +// legacy values. +func validHostname(host string) bool { + host = strings.TrimSuffix(host, ".") + + if len(host) == 0 { + return false + } + + for i, part := range strings.Split(host, ".") { + if part == "" { + // Empty label. + return false + } + if i == 0 && part == "*" { + // Only allow full left-most wildcards, as those are the only ones + // we match, and matching literal '*' characters is probably never + // the expected behavior. + continue + } + for j, c := range part { + if 'a' <= c && c <= 'z' { + continue + } + if '0' <= c && c <= '9' { + continue + } + if 'A' <= c && c <= 'Z' { + continue + } + if c == '-' && j != 0 { + continue + } + if c == '_' { + // _ is not a valid character in hostnames, but it's commonly + // found in deployments outside the WebPKI. + continue + } + return false + } + } + + 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 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() && validHostname(c.Subject.CommonName) +} + func matchHostnames(pattern, host string) bool { host = strings.TrimSuffix(host, ".") pattern = strings.TrimSuffix(pattern, ".") @@ -940,15 +998,16 @@ func (c *Certificate) VerifyHostname(h string) error { lowered := toLowerCaseASCII(h) - if c.hasSANExtension() { + if c.commonNameAsHostname() { + if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) { + return nil + } + } else { for _, match := range c.DNSNames { if matchHostnames(toLowerCaseASCII(match), lowered) { return nil } } - // If Subject Alt Name is given, we ignore the common name. - } else if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) { - return nil } return HostnameError{c, h} diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go index bd3df479078..76841458396 100644 --- a/libgo/go/crypto/x509/verify_test.go +++ b/libgo/go/crypto/x509/verify_test.go @@ -15,8 +15,6 @@ import ( "time" ) -var supportSHA2 = true - type verifyTest struct { leaf string intermediates []string @@ -27,6 +25,7 @@ type verifyTest struct { keyUsages []ExtKeyUsage testSystemRootsError bool sha2 bool + ignoreCN bool errorCallback func(*testing.T, int, error) bool expectedChains [][]string @@ -73,7 +72,16 @@ var verifyTests = []verifyTest{ currentTime: 1395785200, dnsName: "www.example.com", - errorCallback: expectHostnameError, + errorCallback: expectHostnameError("certificate is valid for"), + }, + { + leaf: googleLeaf, + intermediates: []string{giag2Intermediate}, + roots: []string{geoTrustRoot}, + currentTime: 1395785200, + dnsName: "1.2.3.4", + + errorCallback: expectHostnameError("doesn't contain any IP SANs"), }, { leaf: googleLeaf, @@ -250,7 +258,7 @@ var verifyTests = []verifyTest{ dnsName: "notfoo.example", systemSkip: true, - errorCallback: expectHostnameError, + errorCallback: expectHostnameError("certificate is valid for"), }, { // The issuer name in the leaf doesn't exactly match the @@ -283,7 +291,7 @@ var verifyTests = []verifyTest{ currentTime: 1486684488, systemSkip: true, - errorCallback: expectHostnameError, + errorCallback: expectHostnameError("certificate is not valid for any names"), }, { // Test that excluded names are respected. @@ -320,19 +328,77 @@ var verifyTests = []verifyTest{ errorCallback: expectUnhandledCriticalExtension, }, + { + // Test that invalid CN are ignored. + leaf: invalidCNWithoutSAN, + dnsName: "foo,invalid", + roots: []string{invalidCNRoot}, + currentTime: 1540000000, + systemSkip: true, + + errorCallback: expectHostnameError("Common Name is not a valid hostname"), + }, + { + // Test that valid CN are respected. + leaf: validCNWithoutSAN, + dnsName: "foo.example.com", + roots: []string{invalidCNRoot}, + currentTime: 1540000000, + systemSkip: true, + + expectedChains: [][]string{ + {"foo.example.com", "Test root"}, + }, + }, + // Replicate CN tests with ignoreCN = true + { + leaf: ignoreCNWithSANLeaf, + dnsName: "foo.example.com", + roots: []string{ignoreCNWithSANRoot}, + currentTime: 1486684488, + systemSkip: true, + ignoreCN: true, + + errorCallback: expectHostnameError("certificate is not valid for any names"), + }, + { + leaf: invalidCNWithoutSAN, + dnsName: "foo,invalid", + roots: []string{invalidCNRoot}, + currentTime: 1540000000, + systemSkip: true, + ignoreCN: true, + + errorCallback: expectHostnameError("Common Name is not a valid hostname"), + }, + { + leaf: validCNWithoutSAN, + dnsName: "foo.example.com", + roots: []string{invalidCNRoot}, + currentTime: 1540000000, + systemSkip: true, + ignoreCN: true, + + errorCallback: expectHostnameError("not valid for any names"), + }, } -func expectHostnameError(t *testing.T, i int, err error) (ok bool) { - if _, ok := err.(HostnameError); !ok { - t.Errorf("#%d: error was not a HostnameError: %s", i, err) - return false +func expectHostnameError(msg string) func(*testing.T, int, error) bool { + return func(t *testing.T, i int, err error) (ok bool) { + if _, ok := err.(HostnameError); !ok { + t.Errorf("#%d: error was not a HostnameError: %v", i, err) + return false + } + if !strings.Contains(err.Error(), msg) { + t.Errorf("#%d: HostnameError did not contain %q: %v", i, msg, err) + } + return true } - return true } func expectExpired(t *testing.T, i int, err error) (ok bool) { if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != Expired { - t.Errorf("#%d: error was not Expired: %s", i, err) + t.Errorf("#%d: error was not Expired: %v", i, err) return false } return true @@ -340,7 +406,7 @@ func expectExpired(t *testing.T, i int, err error) (ok bool) { func expectUsageError(t *testing.T, i int, err error) (ok bool) { if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != IncompatibleUsage { - t.Errorf("#%d: error was not IncompatibleUsage: %s", i, err) + t.Errorf("#%d: error was not IncompatibleUsage: %v", i, err) return false } return true @@ -349,11 +415,11 @@ func expectUsageError(t *testing.T, i int, err error) (ok bool) { func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) { e, ok := err.(UnknownAuthorityError) if !ok { - t.Errorf("#%d: error was not UnknownAuthorityError: %s", i, err) + t.Errorf("#%d: error was not UnknownAuthorityError: %v", i, err) return false } if e.Cert == nil { - t.Errorf("#%d: error was UnknownAuthorityError, but missing Cert: %s", i, err) + t.Errorf("#%d: error was UnknownAuthorityError, but missing Cert: %v", i, err) return false } return true @@ -361,7 +427,7 @@ func expectAuthorityUnknown(t *testing.T, i int, err error) (ok bool) { func expectSystemRootsError(t *testing.T, i int, err error) bool { if _, ok := err.(SystemRootsError); !ok { - t.Errorf("#%d: error was not SystemRootsError: %s", i, err) + t.Errorf("#%d: error was not SystemRootsError: %v", i, err) return false } return true @@ -373,7 +439,7 @@ func expectHashError(t *testing.T, i int, err error) bool { return false } if expected := "algorithm unimplemented"; !strings.Contains(err.Error(), expected) { - t.Errorf("#%d: error resulting from invalid hash didn't contain '%s', rather it was: %s", i, expected, err) + t.Errorf("#%d: error resulting from invalid hash didn't contain '%s', rather it was: %v", i, expected, err) return false } return true @@ -381,7 +447,7 @@ func expectHashError(t *testing.T, i int, err error) bool { func expectSubjectIssuerMismatcthError(t *testing.T, i int, err error) (ok bool) { if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != NameMismatch { - t.Errorf("#%d: error was not a NameMismatch: %s", i, err) + t.Errorf("#%d: error was not a NameMismatch: %v", i, err) return false } return true @@ -389,7 +455,7 @@ func expectSubjectIssuerMismatcthError(t *testing.T, i int, err error) (ok bool) func expectNameConstraintsError(t *testing.T, i int, err error) (ok bool) { if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != CANotAuthorizedForThisName { - t.Errorf("#%d: error was not a CANotAuthorizedForThisName: %s", i, err) + t.Errorf("#%d: error was not a CANotAuthorizedForThisName: %v", i, err) return false } return true @@ -397,7 +463,7 @@ func expectNameConstraintsError(t *testing.T, i int, err error) (ok bool) { func expectNotAuthorizedError(t *testing.T, i int, err error) (ok bool) { if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != NotAuthorizedToSign { - t.Errorf("#%d: error was not a NotAuthorizedToSign: %s", i, err) + t.Errorf("#%d: error was not a NotAuthorizedToSign: %v", i, err) return false } return true @@ -405,7 +471,7 @@ func expectNotAuthorizedError(t *testing.T, i int, err error) (ok bool) { func expectUnhandledCriticalExtension(t *testing.T, i int, err error) (ok bool) { if _, ok := err.(UnhandledCriticalExtension); !ok { - t.Errorf("#%d: error was not an UnhandledCriticalExtension: %s", i, err) + t.Errorf("#%d: error was not an UnhandledCriticalExtension: %v", i, err) return false } return true @@ -420,6 +486,9 @@ func certificateFromPEM(pemBytes string) (*Certificate, error) { } func testVerify(t *testing.T, useSystemRoots bool) { + defer func(savedIgnoreCN bool) { + ignoreCN = savedIgnoreCN + }(ignoreCN) for i, test := range verifyTests { if useSystemRoots && test.systemSkip { continue @@ -427,10 +496,8 @@ func testVerify(t *testing.T, useSystemRoots bool) { if runtime.GOOS == "windows" && test.testSystemRootsError { continue } - if useSystemRoots && !supportSHA2 && test.sha2 { - continue - } + ignoreCN = test.ignoreCN opts := VerifyOptions{ Intermediates: NewCertPool(), DNSName: test.dnsName, @@ -459,7 +526,7 @@ func testVerify(t *testing.T, useSystemRoots bool) { leaf, err := certificateFromPEM(test.leaf) if err != nil { - t.Errorf("#%d: failed to parse leaf: %s", i, err) + t.Errorf("#%d: failed to parse leaf: %v", i, err) return } @@ -477,7 +544,7 @@ func testVerify(t *testing.T, useSystemRoots bool) { } if test.errorCallback == nil && err != nil { - t.Errorf("#%d: unexpected error: %s", i, err) + t.Errorf("#%d: unexpected error: %v", i, err) } if test.errorCallback != nil { if !test.errorCallback(t, i, err) { @@ -1518,6 +1585,95 @@ yU1yRHUqUYpN0DWFpsPbBqgM6uUAVO2ayBFhPgWUaqkmSbZ/Nq7isGvknaTmcIwT +NQCZDd5eFeU8PpNX7rgaYE4GPq+EEmLVCBYmdctr8QVdqJ//8Xu3+1phjDy -----END CERTIFICATE-----` +const invalidCNRoot = ` +-----BEGIN CERTIFICATE----- +MIIBFjCBvgIJAIsu4r+jb70UMAoGCCqGSM49BAMCMBQxEjAQBgNVBAsMCVRlc3Qg +cm9vdDAeFw0xODA3MTExODMyMzVaFw0yODA3MDgxODMyMzVaMBQxEjAQBgNVBAsM +CVRlc3Qgcm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABF6oDgMg0LV6YhPj +QXaPXYCc2cIyCdqp0ROUksRz0pOLTc5iY2nraUheRUD1vRRneq7GeXOVNn7uXONg +oCGMjNwwCgYIKoZIzj0EAwIDRwAwRAIgDSiwgIn8g1lpruYH0QD1GYeoWVunfmrI +XzZZl0eW/ugCICgOfXeZ2GGy3wIC0352BaC3a8r5AAb2XSGNe+e9wNN6 +-----END CERTIFICATE----- +` + +const invalidCNWithoutSAN = ` +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 07:ba:bc:b7:d9:ab:0c:02:fe:50:1d:4e:15:a3:0d:e4:11:16:14:a2 + Signature Algorithm: ecdsa-with-SHA256 + Issuer: OU = Test root + Validity + Not Before: Jul 11 18:35:21 2018 GMT + Not After : Jul 8 18:35:21 2028 GMT + Subject: CN = "foo,invalid" + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:a7:a6:7c:22:33:a7:47:7f:08:93:2d:5f:61:35: + 2e:da:45:67:76:f2:97:73:18:b0:01:12:4a:1a:d5: + b7:6f:41:3c:bb:05:69:f4:06:5d:ff:eb:2b:a7:85: + 0b:4c:f7:45:4e:81:40:7a:a9:c6:1d:bb:ba:d9:b9: + 26:b3:ca:50:90 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + Signature Algorithm: ecdsa-with-SHA256 + 30:45:02:21:00:85:96:75:b6:72:3c:67:12:a0:7f:86:04:81: + d2:dd:c8:67:50:d7:5f:85:c0:54:54:fc:e6:6b:45:08:93:d3: + 2a:02:20:60:86:3e:d6:28:a6:4e:da:dd:6e:95:89:cc:00:76: + 78:1c:03:80:85:a6:5a:0b:eb:c5:f3:9c:2e:df:ef:6e:fa +-----BEGIN CERTIFICATE----- +MIIBJDCBywIUB7q8t9mrDAL+UB1OFaMN5BEWFKIwCgYIKoZIzj0EAwIwFDESMBAG +A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4MzUyMVoXDTI4MDcwODE4MzUyMVow +FjEUMBIGA1UEAwwLZm9vLGludmFsaWQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC +AASnpnwiM6dHfwiTLV9hNS7aRWd28pdzGLABEkoa1bdvQTy7BWn0Bl3/6yunhQtM +90VOgUB6qcYdu7rZuSazylCQMAoGCCqGSM49BAMCA0gAMEUCIQCFlnW2cjxnEqB/ +hgSB0t3IZ1DXX4XAVFT85mtFCJPTKgIgYIY+1iimTtrdbpWJzAB2eBwDgIWmWgvr +xfOcLt/vbvo= +-----END CERTIFICATE----- +` + +const validCNWithoutSAN = ` +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 07:ba:bc:b7:d9:ab:0c:02:fe:50:1d:4e:15:a3:0d:e4:11:16:14:a4 + Signature Algorithm: ecdsa-with-SHA256 + Issuer: OU = Test root + Validity + Not Before: Jul 11 18:47:24 2018 GMT + Not After : Jul 8 18:47:24 2028 GMT + Subject: CN = foo.example.com + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:a7:a6:7c:22:33:a7:47:7f:08:93:2d:5f:61:35: + 2e:da:45:67:76:f2:97:73:18:b0:01:12:4a:1a:d5: + b7:6f:41:3c:bb:05:69:f4:06:5d:ff:eb:2b:a7:85: + 0b:4c:f7:45:4e:81:40:7a:a9:c6:1d:bb:ba:d9:b9: + 26:b3:ca:50:90 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + Signature Algorithm: ecdsa-with-SHA256 + 30:44:02:20:53:6c:d7:b7:59:61:51:72:a5:18:a3:4b:0d:52: + ea:15:fa:d0:93:30:32:54:4b:ed:0f:58:85:b8:a8:1a:82:3b: + 02:20:14:77:4b:0e:7e:4f:0a:4f:64:26:97:dc:d0:ed:aa:67: + 1d:37:85:da:b4:87:ba:25:1c:2a:58:f7:23:11:8b:3d +-----BEGIN CERTIFICATE----- +MIIBJzCBzwIUB7q8t9mrDAL+UB1OFaMN5BEWFKQwCgYIKoZIzj0EAwIwFDESMBAG +A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4NDcyNFoXDTI4MDcwODE4NDcyNFow +GjEYMBYGA1UEAwwPZm9vLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D +AQcDQgAEp6Z8IjOnR38Iky1fYTUu2kVndvKXcxiwARJKGtW3b0E8uwVp9AZd/+sr +p4ULTPdFToFAeqnGHbu62bkms8pQkDAKBggqhkjOPQQDAgNHADBEAiBTbNe3WWFR +cqUYo0sNUuoV+tCTMDJUS+0PWIW4qBqCOwIgFHdLDn5PCk9kJpfc0O2qZx03hdq0 +h7olHCpY9yMRiz0= +-----END CERTIFICATE----- +` + var unknownAuthorityErrorTests = []struct { cert string expected string @@ -1535,7 +1691,7 @@ func TestUnknownAuthorityError(t *testing.T) { } c, err := ParseCertificate(der.Bytes) if err != nil { - t.Errorf("#%d: Unable to parse certificate -> %s", i, err) + t.Errorf("#%d: Unable to parse certificate -> %v", i, err) } uae := &UnknownAuthorityError{ Cert: c, @@ -1707,3 +1863,28 @@ UNhY4JhezH9gQYqvDMWrWDAbBgNVHSMEFDASgBArF29S5Bnqw7de8GzGA1nfMAoG CCqGSM49BAMCA0gAMEUCIQClA3d4tdrDu9Eb5ZBpgyC+fU1xTZB0dKQHz6M5fPZA 2AIgN96lM+CPGicwhN24uQI6flOsO3H0TJ5lNzBYLtnQtlc= -----END CERTIFICATE-----` + +func TestValidHostname(t *testing.T) { + tests := []struct { + host string + want bool + }{ + {"example.com", true}, + {"eXample123-.com", true}, + {"-eXample123-.com", false}, + {"", false}, + {".", false}, + {"example..com", false}, + {".example.com", false}, + {"*.example.com", true}, + {"*foo.example.com", false}, + {"foo.*.example.com", false}, + {"exa_mple.com", true}, + {"foo,bar", false}, + } + for _, tt := range tests { + if got := validHostname(tt.host); got != tt.want { + t.Errorf("validHostname(%q) = %v, want %v", tt.host, got, tt.want) + } + } +} diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go index ee08dd9797e..2e72471de28 100644 --- a/libgo/go/crypto/x509/x509.go +++ b/libgo/go/crypto/x509/x509.go @@ -420,10 +420,10 @@ func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm // https://tools.ietf.org/html/rfc3447#section-8.1), that the // salt length matches the hash length, and that the trailer // field has the default value. - if !bytes.Equal(params.Hash.Parameters.FullBytes, asn1.NullBytes) || + if (len(params.Hash.Parameters.FullBytes) != 0 && !bytes.Equal(params.Hash.Parameters.FullBytes, asn1.NullBytes)) || !params.MGF.Algorithm.Equal(oidMGF1) || !mgf1HashFunc.Algorithm.Equal(params.Hash.Algorithm) || - !bytes.Equal(mgf1HashFunc.Parameters.FullBytes, asn1.NullBytes) || + (len(mgf1HashFunc.Parameters.FullBytes) != 0 && !bytes.Equal(mgf1HashFunc.Parameters.FullBytes, asn1.NullBytes)) || params.TrailerField != 1 { return UnknownSignatureAlgorithm } @@ -843,23 +843,16 @@ func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature } func (c *Certificate) hasNameConstraints() bool { - for _, e := range c.Extensions { - if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 && e.Id[3] == 30 { - return true - } - } - - return false + return oidInExtensions(oidExtensionNameConstraints, c.Extensions) } -func (c *Certificate) getSANExtension() ([]byte, bool) { +func (c *Certificate) getSANExtension() []byte { for _, e := range c.Extensions { - if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 && e.Id[3] == 17 { - return e.Value, true + if e.Id.Equal(oidExtensionSubjectAltName) { + return e.Value } } - - return nil, false + return nil } func signaturePublicKeyAlgoMismatchError(expectedPubKeyAlgo PublicKeyAlgorithm, pubKey interface{}) error { @@ -1056,7 +1049,7 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{ namedCurveOID := new(asn1.ObjectIdentifier) rest, err := asn1.Unmarshal(paramsData, namedCurveOID) if err != nil { - return nil, err + 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") @@ -1952,7 +1945,8 @@ func buildExtensions(template *Certificate, subjectIsEmpty bool, authorityKeyId } // Adding another extension here? Remember to update the maximum number - // of elements in the make() at the top of the function. + // of elements in the make() at the top of the function and the list of + // template fields used in CreateCertificate documentation. return append(ret[:n], template.ExtraExtensions...), nil } @@ -2039,11 +2033,39 @@ func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgori var emptyASN1Subject = []byte{0x30, 0} // CreateCertificate creates a new X.509v3 certificate based on a template. -// The following members of template are used: AuthorityKeyId, -// BasicConstraintsValid, DNSNames, ExcludedDNSDomains, ExtKeyUsage, -// IsCA, KeyUsage, MaxPathLen, MaxPathLenZero, NotAfter, NotBefore, -// PermittedDNSDomains, PermittedDNSDomainsCritical, SerialNumber, -// SignatureAlgorithm, Subject, SubjectKeyId, and UnknownExtKeyUsage. +// The following members of template are used: +// +// - AuthorityKeyId +// - BasicConstraintsValid +// - CRLDistributionPoints +// - DNSNames +// - EmailAddresses +// - ExcludedDNSDomains +// - ExcludedEmailAddresses +// - ExcludedIPRanges +// - ExcludedURIDomains +// - ExtKeyUsage +// - ExtraExtensions +// - IsCA +// - IssuingCertificateURL +// - KeyUsage +// - MaxPathLen +// - MaxPathLenZero +// - NotAfter +// - NotBefore +// - OCSPServer +// - PermittedDNSDomains +// - PermittedDNSDomainsCritical +// - PermittedEmailAddresses +// - PermittedIPRanges +// - PermittedURIDomains +// - PolicyIdentifiers +// - SerialNumber +// - SignatureAlgorithm +// - Subject +// - SubjectKeyId +// - URIs +// - UnknownExtKeyUsage // // 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 @@ -2317,7 +2339,7 @@ func newRawAttributes(attributes []pkix.AttributeTypeAndValueSET) ([]asn1.RawVal return rawAttributes, nil } -// parseRawAttributes Unmarshals RawAttributes intos AttributeTypeAndValueSETs. +// parseRawAttributes Unmarshals RawAttributes into AttributeTypeAndValueSETs. func parseRawAttributes(rawAttributes []asn1.RawValue) []pkix.AttributeTypeAndValueSET { var attributes []pkix.AttributeTypeAndValueSET for _, rawAttr := range rawAttributes { @@ -2365,9 +2387,18 @@ func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) } // CreateCertificateRequest creates a new certificate request based on a -// template. The following members of template are used: Attributes, DNSNames, -// EmailAddresses, ExtraExtensions, IPAddresses, URIs, SignatureAlgorithm, and -// Subject. The private key is the private key of the signer. +// template. The following members of template are used: +// +// - Attributes +// - DNSNames +// - EmailAddresses +// - ExtraExtensions +// - IPAddresses +// - URIs +// - SignatureAlgorithm +// - Subject +// +// The private key is the private key of the signer. // // The returned slice is the certificate request in DER encoding. // @@ -2410,70 +2441,57 @@ func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv extensions = append(extensions, template.ExtraExtensions...) - var attributes []pkix.AttributeTypeAndValueSET - attributes = append(attributes, template.Attributes...) + // Make a copy of template.Attributes because we may alter it below. + attributes := make([]pkix.AttributeTypeAndValueSET, 0, len(template.Attributes)) + for _, attr := range template.Attributes { + values := make([][]pkix.AttributeTypeAndValue, len(attr.Value)) + copy(values, attr.Value) + attributes = append(attributes, pkix.AttributeTypeAndValueSET{ + Type: attr.Type, + Value: values, + }) + } + extensionsAppended := false if len(extensions) > 0 { - // specifiedExtensions contains all the extensions that we - // found specified via template.Attributes. - specifiedExtensions := make(map[string]bool) - - for _, atvSet := range template.Attributes { - if !atvSet.Type.Equal(oidExtensionRequest) { + // Append the extensions to an existing attribute if possible. + for _, atvSet := range attributes { + if !atvSet.Type.Equal(oidExtensionRequest) || len(atvSet.Value) == 0 { continue } + // specifiedExtensions contains all the extensions that we + // found specified via template.Attributes. + specifiedExtensions := make(map[string]bool) + for _, atvs := range atvSet.Value { for _, atv := range atvs { specifiedExtensions[atv.Type.String()] = true } } - } - atvs := make([]pkix.AttributeTypeAndValue, 0, len(extensions)) - for _, e := range extensions { - if specifiedExtensions[e.Id.String()] { - // Attributes already contained a value for - // this extension and it takes priority. - continue + newValue := make([]pkix.AttributeTypeAndValue, 0, len(atvSet.Value[0])+len(extensions)) + newValue = append(newValue, atvSet.Value[0]...) + + for _, e := range extensions { + if specifiedExtensions[e.Id.String()] { + // Attributes already contained a value for + // this extension and it takes priority. + continue + } + + newValue = append(newValue, pkix.AttributeTypeAndValue{ + // There is no place for the critical + // flag in an AttributeTypeAndValue. + Type: e.Id, + Value: e.Value, + }) } - atvs = append(atvs, pkix.AttributeTypeAndValue{ - // There is no place for the critical flag in a CSR. - Type: e.Id, - Value: e.Value, - }) - } - - // Append the extensions to an existing attribute if possible. - appended := false - for _, atvSet := range attributes { - if !atvSet.Type.Equal(oidExtensionRequest) || len(atvSet.Value) == 0 { - continue - } - - atvSet.Value[0] = append(atvSet.Value[0], atvs...) - appended = true + atvSet.Value[0] = newValue + extensionsAppended = true break } - - // Otherwise, add a new attribute for the extensions. - if !appended { - attributes = append(attributes, pkix.AttributeTypeAndValueSET{ - Type: oidExtensionRequest, - Value: [][]pkix.AttributeTypeAndValue{ - atvs, - }, - }) - } - } - - asn1Subject := template.RawSubject - if len(asn1Subject) == 0 { - asn1Subject, err = asn1.Marshal(template.Subject.ToRDNSequence()) - if err != nil { - return - } } rawAttributes, err := newRawAttributes(attributes) @@ -2481,6 +2499,38 @@ func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv return } + // If not included in attributes, add a new attribute for the + // extensions. + if len(extensions) > 0 && !extensionsAppended { + attr := struct { + Type asn1.ObjectIdentifier + Value [][]pkix.Extension `asn1:"set"` + }{ + Type: oidExtensionRequest, + Value: [][]pkix.Extension{extensions}, + } + + b, err := asn1.Marshal(attr) + if err != nil { + return nil, errors.New("x509: failed to serialise extensions attribute: " + err.Error()) + } + + var rawValue asn1.RawValue + if _, err := asn1.Unmarshal(b, &rawValue); err != nil { + return nil, err + } + + rawAttributes = append(rawAttributes, rawValue) + } + + asn1Subject := template.RawSubject + if len(asn1Subject) == 0 { + asn1Subject, err = asn1.Marshal(template.Subject.ToRDNSequence()) + if err != nil { + return nil, err + } + } + tbsCSR := tbsCertificateRequest{ Version: 0, // PKCS #10, RFC 2986 Subject: asn1.RawValue{FullBytes: asn1Subject}, diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go index 7d75727a8ca..388156e2097 100644 --- a/libgo/go/crypto/x509/x509_test.go +++ b/libgo/go/crypto/x509/x509_test.go @@ -551,7 +551,7 @@ func TestCreateSelfSignedCertificate(t *testing.T) { UnknownExtKeyUsage: testUnknownExtKeyUsage, BasicConstraintsValid: true, - IsCA: true, + IsCA: true, OCSPServer: []string{"http://ocsp.example.com"}, IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"}, @@ -946,19 +946,52 @@ qsGZWxzFvvkXUkQSl0dQQ5jO/FtUJcAVXVVp20LxPemfatAHpW31WdJYeWSQWky2 +f9b5TXKXVyjlUL7uHxowWrT2AtTchDH22wTEtqLEF9Z3Q== -----END CERTIFICATE-----` +// openssl req -newkey rsa:2048 -keyout test.key -sha256 -sigopt \ +// rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 -sigopt rsa_mgf1_md:sha256 \ +// -x509 -days 3650 -nodes -subj '/C=US/ST=CA/L=SF/O=Test/CN=Test' -out \ +// test.pem +var rsaPSSSelfSignedOpenSSL110PEM = `-----BEGIN CERTIFICATE----- +MIIDwDCCAnigAwIBAgIJAM9LAMHTE5xpMD0GCSqGSIb3DQEBCjAwoA0wCwYJYIZI +AWUDBAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIDAgEgMEUxCzAJBgNV +BAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDTALBgNVBAoMBFRlc3Qx +DTALBgNVBAMMBFRlc3QwHhcNMTgwMjIyMjIxMzE4WhcNMjgwMjIwMjIxMzE4WjBF +MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMQ0wCwYDVQQK +DARUZXN0MQ0wCwYDVQQDDARUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA4Zrsydod+GoTAJLLutWNF87qhhVPBsK1zB1Gj+NAAe4+VbrZ1E41H1wp +qITx7DA8DRtJEf+NqrTAnAdZWBG/tAOA5LfXVax0ZSQtLnYLSeylLoMtDyY3eFAj +TmuTOoyVy6raktowCnHCh01NsstqqTfrx6SbmzOmDmKTkq/I+7K0MCVsn41xRDVM ++ShD0WGFGioEGoiWnFSWupxJDA3Q6jIDEygVwNKHwnhv/2NgG2kqZzrZSQA67en0 +iKAXtoDNPpmyD5oS9YbEJ+2Nbm7oLeON30i6kZvXKIzJXx+UWViazHZqnsi5rQ8G +RHF+iVFXsqd0MzDKmkKOT5FDhrsbKQIDAQABo1MwUTAdBgNVHQ4EFgQU9uFY/nlg +gLH00NBnr/o7QvpN9ugwHwYDVR0jBBgwFoAU9uFY/nlggLH00NBnr/o7QvpN9ugw +DwYDVR0TAQH/BAUwAwEB/zA9BgkqhkiG9w0BAQowMKANMAsGCWCGSAFlAwQCAaEa +MBgGCSqGSIb3DQEBCDALBglghkgBZQMEAgGiAwIBIAOCAQEAhJzpwxBNGKvzKWDe +WLqv6RMrl/q4GcH3b7M9wjxe0yOm4F+Tb2zJ7re4h+D39YkJf8cX1NV9UQVu6z4s +Fvo2kmlR0qZOXAg5augmCQ1xS0WHFoF6B52anNzHkZQbAIYJ3kGoFsUHzs7Sz7F/ +656FsRpHA9UzJQ3avPPMrA4Y4aoJ7ANJ6XIwTrdWrhULOVuvYRLCl4CdTVztVFX6 +wxX8nS1ISYd8jXPUMgsBKVbWufvLoIymMJW8CZbpprVZel5zFn0bmPrON8IHS30w +Gs+ITJjKEnZgXmAQ25SLKVzkZkBcGANs2GsdHNJ370Puisy0FIPD2NXR5uASAf7J ++w9fjQ== +-----END CERTIFICATE-----` + func TestRSAPSSSelfSigned(t *testing.T) { - der, _ := pem.Decode([]byte(rsaPSSSelfSignedPEM)) - if der == nil { - t.Fatal("Failed to find PEM block") - } + for i, pemBlock := range []string{rsaPSSSelfSignedPEM, rsaPSSSelfSignedOpenSSL110PEM} { + der, _ := pem.Decode([]byte(pemBlock)) + if der == nil { + t.Errorf("#%d: failed to find PEM block", i) + continue + } - cert, err := ParseCertificate(der.Bytes) - if err != nil { - t.Fatal(err) - } + cert, err := ParseCertificate(der.Bytes) + if err != nil { + t.Errorf("#%d: failed to parse: %s", i, err) + continue + } - if err = cert.CheckSignatureFrom(cert); err != nil { - t.Fatal(err) + if err = cert.CheckSignatureFrom(cert); err != nil { + t.Errorf("#%d: signature check failed: %s", i, err) + continue + } } } @@ -1207,8 +1240,9 @@ func TestCertificateRequestOverrides(t *testing.T) { // template. ExtraExtensions: []pkix.Extension{ { - Id: oidExtensionSubjectAltName, - Value: sanContents, + Id: oidExtensionSubjectAltName, + Value: sanContents, + Critical: true, }, }, } @@ -1219,6 +1253,10 @@ func TestCertificateRequestOverrides(t *testing.T) { t.Errorf("Extension did not override template. Got %v\n", csr.DNSNames) } + if len(csr.Extensions) != 1 || !csr.Extensions[0].Id.Equal(oidExtensionSubjectAltName) || !csr.Extensions[0].Critical { + t.Errorf("SAN extension was not faithfully copied, got %#v", csr.Extensions) + } + // If there is already an attribute with X.509 extensions then the // extra extensions should be added to it rather than creating a CSR // with two extension attributes. @@ -1361,7 +1399,7 @@ func TestMaxPathLen(t *testing.T) { NotAfter: time.Unix(100000, 0), BasicConstraintsValid: true, - IsCA: true, + IsCA: true, } cert1 := serialiseAndParse(t, template) @@ -1402,8 +1440,8 @@ func TestNoAuthorityKeyIdInSelfSignedCert(t *testing.T) { NotAfter: time.Unix(100000, 0), BasicConstraintsValid: true, - IsCA: true, - SubjectKeyId: []byte{1, 2, 3, 4}, + IsCA: true, + SubjectKeyId: []byte{1, 2, 3, 4}, } if cert := serialiseAndParse(t, template); len(cert.AuthorityKeyId) != 0 { @@ -1618,10 +1656,43 @@ func TestSystemCertPool(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("not implemented on Windows; Issue 16736, 18609") } - _, err := SystemCertPool() + a, err := SystemCertPool() if err != nil { t.Fatal(err) } + b, err := SystemCertPool() + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(a, b) { + t.Fatal("two calls to SystemCertPool had different results") + } + if ok := b.AppendCertsFromPEM([]byte(` +-----BEGIN CERTIFICATE----- +MIIDBjCCAe6gAwIBAgIRANXM5I3gjuqDfTp/PYrs+u8wDQYJKoZIhvcNAQELBQAw +EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xODAzMjcxOTU2MjFaFw0xOTAzMjcxOTU2 +MjFaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDK+9m3rjsO2Djes6bIYQZ3eV29JF09ZrjOrEHLtaKrD6/acsoSoTsf +cQr+rzzztdB5ijWXCS64zo/0OiqBeZUNZ67jVdToa9qW5UYe2H0Y+ZNdfA5GYMFD +yk/l3/uBu3suTZPfXiW2TjEi27Q8ruNUIZ54DpTcs6y2rBRFzadPWwn/VQMlvRXM +jrzl8Y08dgnYmaAHprxVzwMXcQ/Brol+v9GvjaH1DooHqkn8O178wsPQNhdtvN01 +IXL46cYdcUwWrE/GX5u+9DaSi+0KWxAPQ+NVD5qUI0CKl4714yGGh7feXMjJdHgl +VG4QJZlJvC4FsURgCHJT6uHGIelnSwhbAgMBAAGjVzBVMA4GA1UdDwEB/wQEAwIF +oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMCAGA1UdEQQZMBeC +FVRlc3RTeXN0ZW1DZXJ0UG9vbC5nbzANBgkqhkiG9w0BAQsFAAOCAQEAwuSRx/VR +BKh2ICxZjL6jBwk/7UlU1XKbhQD96RqkidDNGEc6eLZ90Z5XXTurEsXqdm5jQYPs +1cdcSW+fOSMl7MfW9e5tM66FaIPZl9rKZ1r7GkOfgn93xdLAWe8XHd19xRfDreub +YC8DVqgLASOEYFupVSl76ktPfxkU5KCvmUf3P2PrRybk1qLGFytGxfyice2gHSNI +gify3K/+H/7wCkyFW4xYvzl7WW4mXxoqPRPjQt1J423DhnnQ4G1P8V/vhUpXNXOq +N9IEPnWuihC09cyx/WMQIUlWnaQLHdfpPS04Iez3yy2PdfXJzwfPrja7rNE+skK6 +pa/O1nF0AfWOpw== +-----END CERTIFICATE----- + `)); !ok { + t.Fatal("AppendCertsFromPEM failed") + } + if reflect.DeepEqual(a, b) { + t.Fatal("changing one pool modified the other") + } } const emptyNameConstraintsPEM = ` diff --git a/libgo/go/database/sql/convert.go b/libgo/go/database/sql/convert.go index b79ec3f7b27..92a2ebe0e99 100644 --- a/libgo/go/database/sql/convert.go +++ b/libgo/go/database/sql/convert.go @@ -379,10 +379,9 @@ func convertAssign(dest, src interface{}) error { if src == nil { dv.Set(reflect.Zero(dv.Type())) return nil - } else { - dv.Set(reflect.New(dv.Type().Elem())) - return convertAssign(dv.Interface(), src) } + dv.Set(reflect.New(dv.Type().Elem())) + return convertAssign(dv.Interface(), src) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: s := asString(src) i64, err := strconv.ParseInt(s, 10, dv.Type().Bits()) @@ -434,11 +433,10 @@ func strconvErr(err error) error { func cloneBytes(b []byte) []byte { if b == nil { return nil - } else { - c := make([]byte, len(b)) - copy(c, b) - return c } + c := make([]byte, len(b)) + copy(c, b) + return c } func asString(src interface{}) string { diff --git a/libgo/go/database/sql/fakedb_test.go b/libgo/go/database/sql/fakedb_test.go index abb8d40fc02..a21bae61bac 100644 --- a/libgo/go/database/sql/fakedb_test.go +++ b/libgo/go/database/sql/fakedb_test.go @@ -296,10 +296,10 @@ func (db *fakeDB) createTable(name string, columnNames, columnTypes []string) er db.tables = make(map[string]*table) } if _, exist := db.tables[name]; exist { - return fmt.Errorf("table %q already exists", name) + return fmt.Errorf("fakedb: table %q already exists", name) } if len(columnNames) != len(columnTypes) { - return fmt.Errorf("create table of %q len(names) != len(types): %d vs %d", + return fmt.Errorf("fakedb: create table of %q len(names) != len(types): %d vs %d", name, len(columnNames), len(columnTypes)) } db.tables[name] = &table{colname: columnNames, coltype: columnTypes} @@ -365,7 +365,7 @@ func (c *fakeConn) Begin() (driver.Tx, error) { return nil, driver.ErrBadConn } if c.currTx != nil { - return nil, errors.New("already in a transaction") + return nil, errors.New("fakedb: already in a transaction") } c.touchMem() c.currTx = &fakeTx{c: c} @@ -419,13 +419,13 @@ func (c *fakeConn) Close() (err error) { }() c.touchMem() if c.currTx != nil { - return errors.New("can't close fakeConn; in a Transaction") + return errors.New("fakedb: can't close fakeConn; in a Transaction") } if c.db == nil { - return errors.New("can't close fakeConn; already closed") + return errors.New("fakedb: can't close fakeConn; already closed") } if c.stmtsMade > c.stmtsClosed { - return errors.New("can't close; dangling statement(s)") + return errors.New("fakedb: can't close; dangling statement(s)") } c.db = nil return nil @@ -437,7 +437,7 @@ func checkSubsetTypes(allowAny bool, args []driver.NamedValue) error { case int64, float64, bool, nil, []byte, string, time.Time: default: if !allowAny { - return fmt.Errorf("fakedb_test: invalid argument ordinal %[1]d: %[2]v, type %[2]T", arg.Ordinal, arg.Value) + return fmt.Errorf("fakedb: invalid argument ordinal %[1]d: %[2]v, type %[2]T", arg.Ordinal, arg.Value) } } } @@ -729,7 +729,7 @@ func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (d return nil, driver.ErrBadConn } if s.c.isDirtyAndMark() { - return nil, errors.New("session is dirty") + return nil, errors.New("fakedb: session is dirty") } err := checkSubsetTypes(s.c.db.allowAny, args) @@ -765,8 +765,7 @@ func (s *fakeStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (d // Used for some of the concurrent tests. return s.execInsert(args, false) } - fmt.Printf("EXEC statement, cmd=%q: %#v\n", s.cmd, s) - return nil, fmt.Errorf("unimplemented statement Exec command type of %q", s.cmd) + return nil, fmt.Errorf("fakedb: unimplemented statement Exec command type of %q", s.cmd) } // When doInsert is true, add the row to the table. @@ -844,7 +843,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) ( return nil, driver.ErrBadConn } if s.c.isDirtyAndMark() { - return nil, errors.New("session is dirty") + return nil, errors.New("fakedb: session is dirty") } err := checkSubsetTypes(s.c.db.allowAny, args) @@ -900,7 +899,7 @@ func (s *fakeStmt) QueryContext(ctx context.Context, args []driver.NamedValue) ( idx := t.columnIndex(wcol.Column) if idx == -1 { t.mu.Unlock() - return nil, fmt.Errorf("db: invalid where clause column %q", wcol) + return nil, fmt.Errorf("fakedb: invalid where clause column %q", wcol) } tcol := trow.cols[idx] if bs, ok := tcol.([]byte); ok { @@ -1003,7 +1002,7 @@ type rowsCursor struct { err error // a clone of slices to give out to clients, indexed by the - // the original slice's first byte address. we clone them + // original slice's first byte address. we clone them // just so we're able to corrupt them on close. bytesClone map[*byte][]byte diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go index 8f5588ed268..36179855db2 100644 --- a/libgo/go/database/sql/sql.go +++ b/libgo/go/database/sql/sql.go @@ -24,6 +24,7 @@ import ( "reflect" "runtime" "sort" + "strconv" "sync" "sync/atomic" "time" @@ -132,6 +133,31 @@ const ( LevelLinearizable ) +func (i IsolationLevel) String() string { + switch i { + case LevelDefault: + return "Default" + case LevelReadUncommitted: + return "Read Uncommitted" + case LevelReadCommitted: + return "Read Committed" + case LevelWriteCommitted: + return "Write Committed" + case LevelRepeatableRead: + return "Repeatable Read" + case LevelSnapshot: + return "Snapshot" + case LevelSerializable: + return "Serializable" + case LevelLinearizable: + return "Linearizable" + default: + return "IsolationLevel(" + strconv.Itoa(int(i)) + ")" + } +} + +var _ fmt.Stringer = LevelDefault + // TxOptions holds the transaction options to be used in DB.BeginTx. type TxOptions struct { // Isolation is the transaction isolation level. @@ -275,6 +301,10 @@ type Scanner interface { // // An error should be returned if the value cannot be stored // without loss of information. + // + // Reference types such as []byte are only valid until the next call to Scan + // and should not be retained. Their underlying memory is owned by the driver. + // If retention is necessary, copy their values before the next call to Scan. Scan(src interface{}) error } @@ -310,13 +340,17 @@ var ErrNoRows = errors.New("sql: no rows in result set") // // The sql package creates and frees connections automatically; it // also maintains a free pool of idle connections. If the database has -// a concept of per-connection state, such state can only be reliably -// observed within a transaction. Once DB.Begin is called, the +// a concept of per-connection state, such state can be reliably observed +// within a transaction (Tx) or connection (Conn). Once DB.Begin is called, the // returned Tx is bound to a single connection. Once Commit or // Rollback is called on the transaction, that transaction's // connection is returned to DB's idle connection pool. The pool size // can be controlled with SetMaxIdleConns. type DB struct { + // Atomic access only. At top of struct to prevent mis-alignment + // on 32-bit platforms. Of type time.Duration. + waitDuration int64 // Total time waited for new connections. + connector driver.Connector // numClosed is an atomic counter which represents a total number of // closed connections. Stmt.openStmt checks it before cleaning closed @@ -333,15 +367,18 @@ type DB struct { // maybeOpenNewConnections sends on the chan (one send per needed connection) // It is closed during db.Close(). The close tells the connectionOpener // goroutine to exit. - openerCh chan struct{} - resetterCh chan *driverConn - closed bool - dep map[finalCloser]depSet - lastPut map[*driverConn]string // stacktrace of last conn's put; debug only - maxIdle int // zero means defaultMaxIdleConns; negative means 0 - maxOpen int // <= 0 means unlimited - maxLifetime time.Duration // maximum amount of time a connection may be reused - cleanerCh chan struct{} + openerCh chan struct{} + resetterCh chan *driverConn + closed bool + dep map[finalCloser]depSet + lastPut map[*driverConn]string // stacktrace of last conn's put; debug only + maxIdle int // zero means defaultMaxIdleConns; negative means 0 + maxOpen int // <= 0 means unlimited + maxLifetime time.Duration // maximum amount of time a connection may be reused + cleanerCh chan struct{} + waitCount int64 // Total number of connections waited for. + maxIdleClosed int64 // Total number of connections closed due to idle. + maxLifetimeClosed int64 // Total number of connections closed due to max free limit. stop func() // stop cancels the connection opener and the session resetter. } @@ -503,7 +540,7 @@ type driverStmt struct { closeErr error // return value of previous Close call } -// Close ensures dirver.Stmt is only closed once any always returns the same +// Close ensures driver.Stmt is only closed once and always returns the same // result. func (ds *driverStmt) Close() error { ds.Lock() @@ -712,7 +749,9 @@ func (db *DB) Ping() error { return db.PingContext(context.Background()) } -// Close closes the database, releasing any open resources. +// Close closes the database and prevents new queries from starting. +// Close then waits for all queries that have started processing on the server +// to finish. // // It is rare to Close a DB, as the DB handle is meant to be // long-lived and shared between many goroutines. @@ -764,10 +803,13 @@ func (db *DB) maxIdleConnsLocked() int { // SetMaxIdleConns sets the maximum number of connections in the idle // connection pool. // -// If MaxOpenConns is greater than 0 but less than the new MaxIdleConns -// then the new MaxIdleConns will be reduced to match the MaxOpenConns limit +// If MaxOpenConns is greater than 0 but less than the new MaxIdleConns, +// then the new MaxIdleConns will be reduced to match the MaxOpenConns limit. // // If n <= 0, no idle connections are retained. +// +// The default max idle connections is currently 2. This may change in +// a future release. func (db *DB) SetMaxIdleConns(n int) { db.mu.Lock() if n > 0 { @@ -787,6 +829,7 @@ func (db *DB) SetMaxIdleConns(n int) { closing = db.freeConn[maxIdle:] db.freeConn = db.freeConn[:maxIdle] } + db.maxIdleClosed += int64(len(closing)) db.mu.Unlock() for _, c := range closing { c.Close() @@ -797,7 +840,7 @@ func (db *DB) SetMaxIdleConns(n int) { // // If MaxIdleConns is greater than 0 and the new MaxOpenConns is less than // MaxIdleConns, then MaxIdleConns will be reduced to match the new -// MaxOpenConns limit +// MaxOpenConns limit. // // If n <= 0, then there is no limit on the number of open connections. // The default is 0 (unlimited). @@ -879,6 +922,7 @@ func (db *DB) connectionCleaner(d time.Duration) { i-- } } + db.maxLifetimeClosed += int64(len(closing)) db.mu.Unlock() for _, c := range closing { @@ -894,17 +938,39 @@ func (db *DB) connectionCleaner(d time.Duration) { // DBStats contains database statistics. type DBStats struct { - // OpenConnections is the number of open connections to the database. - OpenConnections int + MaxOpenConnections int // Maximum number of open connections to the database. + + // Pool Status + OpenConnections int // The number of established connections both in use and idle. + InUse int // The number of connections currently in use. + Idle int // The number of idle connections. + + // Counters + WaitCount int64 // The total number of connections waited for. + WaitDuration time.Duration // The total time blocked waiting for a new connection. + MaxIdleClosed int64 // The total number of connections closed due to SetMaxIdleConns. + MaxLifetimeClosed int64 // The total number of connections closed due to SetConnMaxLifetime. } // Stats returns database statistics. func (db *DB) Stats() DBStats { + wait := atomic.LoadInt64(&db.waitDuration) + db.mu.Lock() + defer db.mu.Unlock() + stats := DBStats{ + MaxOpenConnections: db.maxOpen, + + Idle: len(db.freeConn), OpenConnections: db.numOpen, + InUse: db.numOpen - len(db.freeConn), + + WaitCount: db.waitCount, + WaitDuration: time.Duration(wait), + MaxIdleClosed: db.maxIdleClosed, + MaxLifetimeClosed: db.maxLifetimeClosed, } - db.mu.Unlock() return stats } @@ -1057,8 +1123,11 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn req := make(chan connRequest, 1) reqKey := db.nextRequestKeyLocked() db.connRequests[reqKey] = req + db.waitCount++ db.mu.Unlock() + waitStart := time.Now() + // Timeout the connection request with the context. select { case <-ctx.Done(): @@ -1067,15 +1136,20 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn db.mu.Lock() delete(db.connRequests, reqKey) db.mu.Unlock() + + atomic.AddInt64(&db.waitDuration, int64(time.Since(waitStart))) + select { default: case ret, ok := <-req: - if ok { + if ok && ret.conn != nil { db.putConn(ret.conn, ret.err, false) } } return nil, ctx.Err() case ret, ok := <-req: + atomic.AddInt64(&db.waitDuration, int64(time.Since(waitStart))) + if !ok { return nil, errDBClosed } @@ -1250,6 +1324,7 @@ func (db *DB) putConnDBLocked(dc *driverConn, err error) bool { return true } else if err == nil && !db.closed && db.maxIdleConnsLocked() > len(db.freeConn) { db.freeConn = append(db.freeConn, dc) + db.maxIdleClosed++ db.startCleanerLocked() return true } @@ -1603,7 +1678,7 @@ func (db *DB) Driver() driver.Driver { // ErrConnDone is returned by any operation that is performed on a connection // that has already been returned to the connection pool. -var ErrConnDone = errors.New("database/sql: connection is already closed") +var ErrConnDone = errors.New("sql: connection is already closed") // Conn returns a single connection by either opening a new connection // or returning an existing connection from the connection pool. Conn will @@ -1851,7 +1926,7 @@ func (tx *Tx) isDone() bool { // ErrTxDone is returned by any operation that is performed on a transaction // that has already been committed or rolled back. -var ErrTxDone = errors.New("sql: Transaction has already been committed or rolled back") +var ErrTxDone = errors.New("sql: transaction has already been committed or rolled back") // close returns the connection to the pool and // must only be called by Tx.rollback or Tx.Commit. @@ -1914,7 +1989,7 @@ func (tx *Tx) closePrepared() { // Commit commits the transaction. func (tx *Tx) Commit() error { // Check context first to avoid transaction leak. - // If put it behind tx.done CompareAndSwap statement, we cant't ensure + // If put it behind tx.done CompareAndSwap statement, we can't ensure // the consistency between tx.done and the real COMMIT operation. select { default: @@ -2262,13 +2337,6 @@ func resultFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, ar return nil, err } - // -1 means the driver doesn't know how to count the number of - // placeholders, so we won't sanity check input here and instead let the - // driver deal with errors. - if want := ds.si.NumInput(); want >= 0 && want != len(dargs) { - return nil, fmt.Errorf("sql: statement expects %d inputs; got %d", want, len(dargs)) - } - resi, err := ctxDriverStmtExec(ctx, ds.si, dargs) if err != nil { return nil, err @@ -2317,7 +2385,7 @@ func (s *Stmt) connStmt(ctx context.Context, strategy connReuseStrategy) (dc *dr } // In a transaction or connection, we always use the connection that the - // the stmt was created on. + // stmt was created on. if s.cg != nil { s.mu.Unlock() dc, releaseConn, err = s.cg.grabConn(ctx) // blocks, waiting for the connection. @@ -2434,24 +2502,11 @@ func (s *Stmt) Query(args ...interface{}) (*Rows, error) { func rowsiFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, args ...interface{}) (driver.Rows, error) { ds.Lock() defer ds.Unlock() - dargs, err := driverArgsConnLocked(ci, ds, args) if err != nil { return nil, err } - - // -1 means the driver doesn't know how to count the number of - // placeholders, so we won't sanity check input here and instead let the - // driver deal with errors. - if want := ds.si.NumInput(); want >= 0 && want != len(dargs) { - return nil, fmt.Errorf("sql: statement expects %d inputs; got %d", want, len(dargs)) - } - - rowsi, err := ctxDriverStmtQuery(ctx, ds.si, dargs) - if err != nil { - return nil, err - } - return rowsi, nil + return ctxDriverStmtQuery(ctx, ds.si, dargs) } // QueryRowContext executes a prepared query statement with the given arguments. @@ -2460,11 +2515,6 @@ func rowsiFromStatement(ctx context.Context, ci driver.Conn, ds *driverStmt, arg // 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. -// -// Example usage: -// -// var name string -// err := nameByUseridStmt.QueryRowContext(ctx, id).Scan(&name) func (s *Stmt) QueryRowContext(ctx context.Context, args ...interface{}) *Row { rows, err := s.QueryContext(ctx, args...) if err != nil { @@ -2533,19 +2583,7 @@ func (s *Stmt) finalClose() error { } // Rows is the result of a query. Its cursor starts before the first row -// of the result set. Use Next to advance through the rows: -// -// rows, err := db.Query("SELECT ...") -// ... -// defer rows.Close() -// for rows.Next() { -// var id int -// var name string -// err = rows.Scan(&id, &name) -// ... -// } -// err = rows.Err() // get any error encountered during iteration -// ... +// of the result set. Use Next to advance from row to row. type Rows struct { dc *driverConn // owned; must call releaseConn when closed to release releaseConn func(error) @@ -2568,6 +2606,9 @@ type Rows struct { } func (rs *Rows) initContextClose(ctx, txctx context.Context) { + if ctx.Done() == nil && (txctx == nil || txctx.Done() == nil) { + return + } ctx, rs.cancel = context.WithCancel(ctx) go rs.awaitDone(ctx, txctx) } @@ -2861,7 +2902,7 @@ func rowsColumnInfoSetupConnLocked(rowsi driver.Rows) []*ColumnType { // // Source values of type time.Time may be scanned into values of type // *time.Time, *interface{}, *string, or *[]byte. When converting to -// the latter two, time.Format3339Nano is used. +// the latter two, time.RFC3339Nano is used. // // Source values of type bool may be scanned into types *bool, // *interface{}, *string, *[]byte, or *RawBytes. @@ -2870,6 +2911,11 @@ func rowsColumnInfoSetupConnLocked(rowsi driver.Rows) []*ColumnType { // string inputs parseable by strconv.ParseBool. func (rs *Rows) Scan(dest ...interface{}) error { rs.closemu.RLock() + + if rs.lasterr != nil && rs.lasterr != io.EOF { + rs.closemu.RUnlock() + return rs.lasterr + } if rs.closed { rs.closemu.RUnlock() return errors.New("sql: Rows are closed") @@ -2885,7 +2931,7 @@ func (rs *Rows) Scan(dest ...interface{}) error { for i, sv := range rs.lastcols { err := convertAssign(dest[i], sv) if err != nil { - return fmt.Errorf("sql: Scan error on column index %d: %v", i, err) + return fmt.Errorf(`sql: Scan error on column index %d, name %q: %v`, i, rs.rowsi.Columns()[i], err) } } return nil @@ -2981,11 +3027,7 @@ func (r *Row) Scan(dest ...interface{}) error { return err } // Make sure the query can be processed to completion with no errors. - if err := r.rows.Close(); err != nil { - return err - } - - return nil + return r.rows.Close() } // A Result summarizes an executed SQL command. diff --git a/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go index ae6bf7102e3..f194744aefe 100644 --- a/libgo/go/database/sql/sql_test.go +++ b/libgo/go/database/sql/sql_test.go @@ -325,8 +325,8 @@ func TestQueryContext(t *testing.T) { } t.Fatalf("Scan: %v", err) } - if index == 2 && err == nil { - t.Fatal("expected an error on last scan") + if index == 2 && err != context.Canceled { + t.Fatalf("Scan: %v; want context.Canceled", err) } got = append(got, r) index++ @@ -1338,6 +1338,57 @@ func TestConnQuery(t *testing.T) { } } +func TestInvalidNilValues(t *testing.T) { + var date1 time.Time + var date2 int + + tests := []struct { + name string + input interface{} + expectedError string + }{ + { + name: "time.Time", + input: &date1, + expectedError: `sql: Scan error on column index 0, name "bdate": unsupported Scan, storing driver.Value type into type *time.Time`, + }, + { + name: "int", + input: &date2, + expectedError: `sql: Scan error on column index 0, name "bdate": converting driver.Value type ("") to a int: invalid syntax`, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + db := newTestDB(t, "people") + defer closeDB(t, db) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + conn, err := db.Conn(ctx) + if err != nil { + t.Fatal(err) + } + conn.dc.ci.(*fakeConn).skipDirtySession = true + defer conn.Close() + + err = conn.QueryRowContext(ctx, "SELECT|people|bdate|age=?", 1).Scan(tt.input) + if err == nil { + t.Fatal("expected error when querying nil column, but succeeded") + } + if err.Error() != tt.expectedError { + t.Fatalf("Expected error: %s\nReceived: %s", tt.expectedError, err.Error()) + } + + err = conn.PingContext(ctx) + if err != nil { + t.Fatal(err) + } + }) + } +} + func TestConnTx(t *testing.T) { db := newTestDB(t, "people") defer closeDB(t, db) @@ -1659,7 +1710,7 @@ func TestQueryRowNilScanDest(t *testing.T) { defer closeDB(t, db) var name *string // nil pointer err := db.QueryRow("SELECT|people|name|").Scan(name) - want := "sql: Scan error on column index 0: destination pointer is nil" + want := `sql: Scan error on column index 0, name "name": destination pointer is nil` if err == nil || err.Error() != want { t.Errorf("error = %q; want %q", err.Error(), want) } diff --git a/libgo/go/debug/dwarf/attr_string.go b/libgo/go/debug/dwarf/attr_string.go new file mode 100644 index 00000000000..34e3659a64c --- /dev/null +++ b/libgo/go/debug/dwarf/attr_string.go @@ -0,0 +1,89 @@ +// Code generated by "stringer -type Attr -trimprefix=Attr"; DO NOT EDIT. + +package dwarf + +import "strconv" + +const _Attr_name = "SiblingLocationNameOrderingByteSizeBitOffsetBitSizeStmtListLowpcHighpcLanguageDiscrDiscrValueVisibilityImportStringLengthCommonRefCompDirConstValueContainingTypeDefaultValueInlineIsOptionalLowerBoundProducerPrototypedReturnAddrStartScopeStrideSizeUpperBoundAbstractOriginAccessibilityAddrClassArtificialBaseTypesCallingCountDataMemberLocDeclColumnDeclFileDeclLineDeclarationDiscrListEncodingExternalFrameBaseFriendIdentifierCaseMacroInfoNamelistItemPrioritySegmentSpecificationStaticLinkTypeUseLocationVarParamVirtualityVtableElemLocAllocatedAssociatedDataLocationStrideEntrypcUseUTF8ExtensionRangesTrampolineCallColumnCallFileCallLineDescription" + +var _Attr_map = map[Attr]string{ + 1: _Attr_name[0:7], + 2: _Attr_name[7:15], + 3: _Attr_name[15:19], + 9: _Attr_name[19:27], + 11: _Attr_name[27:35], + 12: _Attr_name[35:44], + 13: _Attr_name[44:51], + 16: _Attr_name[51:59], + 17: _Attr_name[59:64], + 18: _Attr_name[64:70], + 19: _Attr_name[70:78], + 21: _Attr_name[78:83], + 22: _Attr_name[83:93], + 23: _Attr_name[93:103], + 24: _Attr_name[103:109], + 25: _Attr_name[109:121], + 26: _Attr_name[121:130], + 27: _Attr_name[130:137], + 28: _Attr_name[137:147], + 29: _Attr_name[147:161], + 30: _Attr_name[161:173], + 32: _Attr_name[173:179], + 33: _Attr_name[179:189], + 34: _Attr_name[189:199], + 37: _Attr_name[199:207], + 39: _Attr_name[207:217], + 42: _Attr_name[217:227], + 44: _Attr_name[227:237], + 46: _Attr_name[237:247], + 47: _Attr_name[247:257], + 49: _Attr_name[257:271], + 50: _Attr_name[271:284], + 51: _Attr_name[284:293], + 52: _Attr_name[293:303], + 53: _Attr_name[303:312], + 54: _Attr_name[312:319], + 55: _Attr_name[319:324], + 56: _Attr_name[324:337], + 57: _Attr_name[337:347], + 58: _Attr_name[347:355], + 59: _Attr_name[355:363], + 60: _Attr_name[363:374], + 61: _Attr_name[374:383], + 62: _Attr_name[383:391], + 63: _Attr_name[391:399], + 64: _Attr_name[399:408], + 65: _Attr_name[408:414], + 66: _Attr_name[414:428], + 67: _Attr_name[428:437], + 68: _Attr_name[437:449], + 69: _Attr_name[449:457], + 70: _Attr_name[457:464], + 71: _Attr_name[464:477], + 72: _Attr_name[477:487], + 73: _Attr_name[487:491], + 74: _Attr_name[491:502], + 75: _Attr_name[502:510], + 76: _Attr_name[510:520], + 77: _Attr_name[520:533], + 78: _Attr_name[533:542], + 79: _Attr_name[542:552], + 80: _Attr_name[552:564], + 81: _Attr_name[564:570], + 82: _Attr_name[570:577], + 83: _Attr_name[577:584], + 84: _Attr_name[584:593], + 85: _Attr_name[593:599], + 86: _Attr_name[599:609], + 87: _Attr_name[609:619], + 88: _Attr_name[619:627], + 89: _Attr_name[627:635], + 90: _Attr_name[635:646], +} + +func (i Attr) String() string { + if str, ok := _Attr_map[i]; ok { + return str + } + return "Attr(" + strconv.FormatInt(int64(i), 10) + ")" +} diff --git a/libgo/go/debug/dwarf/class_string.go b/libgo/go/debug/dwarf/class_string.go index d57d9f71c43..a6aabff524f 100644 --- a/libgo/go/debug/dwarf/class_string.go +++ b/libgo/go/debug/dwarf/class_string.go @@ -1,16 +1,16 @@ -// generated by stringer -type=Class; DO NOT EDIT +// Code generated by "stringer -type=Class"; DO NOT EDIT. package dwarf -import "fmt" +import "strconv" const _Class_name = "ClassUnknownClassAddressClassBlockClassConstantClassExprLocClassFlagClassLinePtrClassLocListPtrClassMacPtrClassRangeListPtrClassReferenceClassReferenceSigClassStringClassReferenceAltClassStringAlt" var _Class_index = [...]uint8{0, 12, 24, 34, 47, 59, 68, 80, 95, 106, 123, 137, 154, 165, 182, 196} func (i Class) String() string { - if i < 0 || i+1 >= Class(len(_Class_index)) { - return fmt.Sprintf("Class(%d)", i) + if i < 0 || i >= Class(len(_Class_index)-1) { + return "Class(" + strconv.FormatInt(int64(i), 10) + ")" } return _Class_name[_Class_index[i]:_Class_index[i+1]] } diff --git a/libgo/go/debug/dwarf/const.go b/libgo/go/debug/dwarf/const.go index 04d8c506b06..4dda83e6928 100644 --- a/libgo/go/debug/dwarf/const.go +++ b/libgo/go/debug/dwarf/const.go @@ -6,7 +6,7 @@ package dwarf -import "strconv" +//go:generate stringer -type Attr -trimprefix=Attr // An Attr identifies the attribute type in a DWARF Entry's Field. type Attr uint32 @@ -86,99 +86,11 @@ const ( AttrDescription Attr = 0x5A ) -var attrNames = [...]string{ - AttrSibling: "Sibling", - AttrLocation: "Location", - AttrName: "Name", - AttrOrdering: "Ordering", - AttrByteSize: "ByteSize", - AttrBitOffset: "BitOffset", - AttrBitSize: "BitSize", - AttrStmtList: "StmtList", - AttrLowpc: "Lowpc", - AttrHighpc: "Highpc", - AttrLanguage: "Language", - AttrDiscr: "Discr", - AttrDiscrValue: "DiscrValue", - AttrVisibility: "Visibility", - AttrImport: "Import", - AttrStringLength: "StringLength", - AttrCommonRef: "CommonRef", - AttrCompDir: "CompDir", - AttrConstValue: "ConstValue", - AttrContainingType: "ContainingType", - AttrDefaultValue: "DefaultValue", - AttrInline: "Inline", - AttrIsOptional: "IsOptional", - AttrLowerBound: "LowerBound", - AttrProducer: "Producer", - AttrPrototyped: "Prototyped", - AttrReturnAddr: "ReturnAddr", - AttrStartScope: "StartScope", - AttrStrideSize: "StrideSize", - AttrUpperBound: "UpperBound", - AttrAbstractOrigin: "AbstractOrigin", - AttrAccessibility: "Accessibility", - AttrAddrClass: "AddrClass", - AttrArtificial: "Artificial", - AttrBaseTypes: "BaseTypes", - AttrCalling: "Calling", - AttrCount: "Count", - AttrDataMemberLoc: "DataMemberLoc", - AttrDeclColumn: "DeclColumn", - AttrDeclFile: "DeclFile", - AttrDeclLine: "DeclLine", - AttrDeclaration: "Declaration", - AttrDiscrList: "DiscrList", - AttrEncoding: "Encoding", - AttrExternal: "External", - AttrFrameBase: "FrameBase", - AttrFriend: "Friend", - AttrIdentifierCase: "IdentifierCase", - AttrMacroInfo: "MacroInfo", - AttrNamelistItem: "NamelistItem", - AttrPriority: "Priority", - AttrSegment: "Segment", - AttrSpecification: "Specification", - AttrStaticLink: "StaticLink", - AttrType: "Type", - AttrUseLocation: "UseLocation", - AttrVarParam: "VarParam", - AttrVirtuality: "Virtuality", - AttrVtableElemLoc: "VtableElemLoc", - AttrAllocated: "Allocated", - AttrAssociated: "Associated", - AttrDataLocation: "DataLocation", - AttrStride: "Stride", - AttrEntrypc: "Entrypc", - AttrUseUTF8: "UseUTF8", - AttrExtension: "Extension", - AttrRanges: "Ranges", - AttrTrampoline: "Trampoline", - AttrCallColumn: "CallColumn", - AttrCallFile: "CallFile", - AttrCallLine: "CallLine", - AttrDescription: "Description", -} - -func (a Attr) String() string { - if int(a) < len(attrNames) { - s := attrNames[a] - if s != "" { - return s - } - } - return strconv.Itoa(int(a)) -} - func (a Attr) GoString() string { - if int(a) < len(attrNames) { - s := attrNames[a] - if s != "" { - return "dwarf.Attr" + s - } + if str, ok := _Attr_map[a]; ok { + return "dwarf.Attr" + str } - return "dwarf.Attr(" + strconv.FormatInt(int64(a), 10) + ")" + return "dwarf." + a.String() } // A format is a DWARF data encoding format. @@ -218,6 +130,8 @@ const ( formGnuStrpAlt format = 0x1f21 ) +//go:generate stringer -type Tag -trimprefix=Tag + // A Tag is the classification (the type) of an Entry. type Tag uint32 @@ -287,88 +201,11 @@ const ( TagTemplateAlias Tag = 0x43 ) -var tagNames = [...]string{ - TagArrayType: "ArrayType", - TagClassType: "ClassType", - TagEntryPoint: "EntryPoint", - TagEnumerationType: "EnumerationType", - TagFormalParameter: "FormalParameter", - TagImportedDeclaration: "ImportedDeclaration", - TagLabel: "Label", - TagLexDwarfBlock: "LexDwarfBlock", - TagMember: "Member", - TagPointerType: "PointerType", - TagReferenceType: "ReferenceType", - TagCompileUnit: "CompileUnit", - TagStringType: "StringType", - TagStructType: "StructType", - TagSubroutineType: "SubroutineType", - TagTypedef: "Typedef", - TagUnionType: "UnionType", - TagUnspecifiedParameters: "UnspecifiedParameters", - TagVariant: "Variant", - TagCommonDwarfBlock: "CommonDwarfBlock", - TagCommonInclusion: "CommonInclusion", - TagInheritance: "Inheritance", - TagInlinedSubroutine: "InlinedSubroutine", - TagModule: "Module", - TagPtrToMemberType: "PtrToMemberType", - TagSetType: "SetType", - TagSubrangeType: "SubrangeType", - TagWithStmt: "WithStmt", - TagAccessDeclaration: "AccessDeclaration", - TagBaseType: "BaseType", - TagCatchDwarfBlock: "CatchDwarfBlock", - TagConstType: "ConstType", - TagConstant: "Constant", - TagEnumerator: "Enumerator", - TagFileType: "FileType", - TagFriend: "Friend", - TagNamelist: "Namelist", - TagNamelistItem: "NamelistItem", - TagPackedType: "PackedType", - TagSubprogram: "Subprogram", - TagTemplateTypeParameter: "TemplateTypeParameter", - TagTemplateValueParameter: "TemplateValueParameter", - TagThrownType: "ThrownType", - TagTryDwarfBlock: "TryDwarfBlock", - TagVariantPart: "VariantPart", - TagVariable: "Variable", - TagVolatileType: "VolatileType", - TagDwarfProcedure: "DwarfProcedure", - TagRestrictType: "RestrictType", - TagInterfaceType: "InterfaceType", - TagNamespace: "Namespace", - TagImportedModule: "ImportedModule", - TagUnspecifiedType: "UnspecifiedType", - TagPartialUnit: "PartialUnit", - TagImportedUnit: "ImportedUnit", - TagMutableType: "MutableType", - TagCondition: "Condition", - TagSharedType: "SharedType", - TagTypeUnit: "TypeUnit", - TagRvalueReferenceType: "RvalueReferenceType", - TagTemplateAlias: "TemplateAlias", -} - -func (t Tag) String() string { - if int(t) < len(tagNames) { - s := tagNames[t] - if s != "" { - return s - } - } - return strconv.Itoa(int(t)) -} - func (t Tag) GoString() string { - if int(t) < len(tagNames) { - s := tagNames[t] - if s != "" { - return "dwarf.Tag" + s - } + if t <= TagTemplateAlias { + return "dwarf.Tag" + t.String() } - return "dwarf.Tag(" + strconv.FormatInt(int64(t), 10) + ")" + return "dwarf." + t.String() } // Location expression operators. diff --git a/libgo/go/debug/dwarf/tag_string.go b/libgo/go/debug/dwarf/tag_string.go new file mode 100644 index 00000000000..ac396af050f --- /dev/null +++ b/libgo/go/debug/dwarf/tag_string.go @@ -0,0 +1,44 @@ +// Code generated by "stringer -type Tag -trimprefix=Tag"; DO NOT EDIT. + +package dwarf + +import "strconv" + +const ( + _Tag_name_0 = "ArrayTypeClassTypeEntryPointEnumerationTypeFormalParameter" + _Tag_name_1 = "ImportedDeclaration" + _Tag_name_2 = "LabelLexDwarfBlock" + _Tag_name_3 = "Member" + _Tag_name_4 = "PointerTypeReferenceTypeCompileUnitStringTypeStructType" + _Tag_name_5 = "SubroutineTypeTypedefUnionTypeUnspecifiedParametersVariantCommonDwarfBlockCommonInclusionInheritanceInlinedSubroutineModulePtrToMemberTypeSetTypeSubrangeTypeWithStmtAccessDeclarationBaseTypeCatchDwarfBlockConstTypeConstantEnumeratorFileTypeFriendNamelistNamelistItemPackedTypeSubprogramTemplateTypeParameterTemplateValueParameterThrownTypeTryDwarfBlockVariantPartVariableVolatileTypeDwarfProcedureRestrictTypeInterfaceTypeNamespaceImportedModuleUnspecifiedTypePartialUnitImportedUnitMutableTypeConditionSharedTypeTypeUnitRvalueReferenceTypeTemplateAlias" +) + +var ( + _Tag_index_0 = [...]uint8{0, 9, 18, 28, 43, 58} + _Tag_index_2 = [...]uint8{0, 5, 18} + _Tag_index_4 = [...]uint8{0, 11, 24, 35, 45, 55} + _Tag_index_5 = [...]uint16{0, 14, 21, 30, 51, 58, 74, 89, 100, 117, 123, 138, 145, 157, 165, 182, 190, 205, 214, 222, 232, 240, 246, 254, 266, 276, 286, 307, 329, 339, 352, 363, 371, 383, 397, 409, 422, 431, 445, 460, 471, 483, 494, 503, 513, 521, 540, 553} +) + +func (i Tag) String() string { + switch { + case 1 <= i && i <= 5: + i -= 1 + return _Tag_name_0[_Tag_index_0[i]:_Tag_index_0[i+1]] + case i == 8: + return _Tag_name_1 + case 10 <= i && i <= 11: + i -= 10 + return _Tag_name_2[_Tag_index_2[i]:_Tag_index_2[i+1]] + case i == 13: + return _Tag_name_3 + case 15 <= i && i <= 19: + i -= 15 + return _Tag_name_4[_Tag_index_4[i]:_Tag_index_4[i+1]] + case 21 <= i && i <= 67: + i -= 21 + return _Tag_name_5[_Tag_index_5[i]:_Tag_index_5[i+1]] + default: + return "Tag(" + strconv.FormatInt(int64(i), 10) + ")" + } +} diff --git a/libgo/go/debug/elf/elf.go b/libgo/go/debug/elf/elf.go index c8a4fe6e610..07c03e79996 100644 --- a/libgo/go/debug/elf/elf.go +++ b/libgo/go/debug/elf/elf.go @@ -11,7 +11,10 @@ * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $ * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $ * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $ + * "System V ABI" (http://www.sco.com/developers/gabi/latest/ch4.eheader.html) * "ELF for the ARM® 64-bit Architecture (AArch64)" (ARM IHI 0056B) + * "RISC-V ELF psABI specification" (https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md) + * llvm/BinaryFormat/ELF.h - ELF constants and structures * * Copyright (c) 1996-1998 John D. Polstra. All rights reserved. * Copyright (c) 2001 David E. O'Brien @@ -132,6 +135,9 @@ const ( ELFOSABI_OPENBSD OSABI = 12 /* OpenBSD */ ELFOSABI_OPENVMS OSABI = 13 /* Open VMS */ ELFOSABI_NSK OSABI = 14 /* HP Non-Stop Kernel */ + ELFOSABI_AROS OSABI = 15 /* Amiga Research OS */ + ELFOSABI_FENIXOS OSABI = 16 /* The FenixOS highly scalable multi-core OS */ + ELFOSABI_CLOUDABI OSABI = 17 /* Nuxi CloudABI */ ELFOSABI_ARM OSABI = 97 /* ARM */ ELFOSABI_STANDALONE OSABI = 255 /* Standalone (embedded) application */ ) @@ -152,6 +158,9 @@ var osabiStrings = []intName{ {12, "ELFOSABI_OPENBSD"}, {13, "ELFOSABI_OPENVMS"}, {14, "ELFOSABI_NSK"}, + {15, "ELFOSABI_AROS"}, + {16, "ELFOSABI_FENIXOS"}, + {17, "ELFOSABI_CLOUDABI"}, {97, "ELFOSABI_ARM"}, {255, "ELFOSABI_STANDALONE"}, } @@ -193,50 +202,188 @@ func (i Type) GoString() string { return stringName(uint32(i), typeStrings, true type Machine uint16 const ( - EM_NONE Machine = 0 /* Unknown machine. */ - EM_M32 Machine = 1 /* AT&T WE32100. */ - EM_SPARC Machine = 2 /* Sun SPARC. */ - EM_386 Machine = 3 /* Intel i386. */ - EM_68K Machine = 4 /* Motorola 68000. */ - EM_88K Machine = 5 /* Motorola 88000. */ - EM_860 Machine = 7 /* Intel i860. */ - EM_MIPS Machine = 8 /* MIPS R3000 Big-Endian only. */ - EM_S370 Machine = 9 /* IBM System/370. */ - EM_MIPS_RS3_LE Machine = 10 /* MIPS R3000 Little-Endian. */ - EM_PARISC Machine = 15 /* HP PA-RISC. */ - EM_VPP500 Machine = 17 /* Fujitsu VPP500. */ - EM_SPARC32PLUS Machine = 18 /* SPARC v8plus. */ - EM_960 Machine = 19 /* Intel 80960. */ - EM_PPC Machine = 20 /* PowerPC 32-bit. */ - EM_PPC64 Machine = 21 /* PowerPC 64-bit. */ - EM_S390 Machine = 22 /* IBM System/390. */ - EM_V800 Machine = 36 /* NEC V800. */ - EM_FR20 Machine = 37 /* Fujitsu FR20. */ - EM_RH32 Machine = 38 /* TRW RH-32. */ - EM_RCE Machine = 39 /* Motorola RCE. */ - EM_ARM Machine = 40 /* ARM. */ - EM_SH Machine = 42 /* Hitachi SH. */ - EM_SPARCV9 Machine = 43 /* SPARC v9 64-bit. */ - EM_TRICORE Machine = 44 /* Siemens TriCore embedded processor. */ - EM_ARC Machine = 45 /* Argonaut RISC Core. */ - EM_H8_300 Machine = 46 /* Hitachi H8/300. */ - EM_H8_300H Machine = 47 /* Hitachi H8/300H. */ - EM_H8S Machine = 48 /* Hitachi H8S. */ - EM_H8_500 Machine = 49 /* Hitachi H8/500. */ - EM_IA_64 Machine = 50 /* Intel IA-64 Processor. */ - EM_MIPS_X Machine = 51 /* Stanford MIPS-X. */ - EM_COLDFIRE Machine = 52 /* Motorola ColdFire. */ - EM_68HC12 Machine = 53 /* Motorola M68HC12. */ - EM_MMA Machine = 54 /* Fujitsu MMA. */ - EM_PCP Machine = 55 /* Siemens PCP. */ - EM_NCPU Machine = 56 /* Sony nCPU. */ - EM_NDR1 Machine = 57 /* Denso NDR1 microprocessor. */ - EM_STARCORE Machine = 58 /* Motorola Star*Core processor. */ - EM_ME16 Machine = 59 /* Toyota ME16 processor. */ - EM_ST100 Machine = 60 /* STMicroelectronics ST100 processor. */ - EM_TINYJ Machine = 61 /* Advanced Logic Corp. TinyJ processor. */ - EM_X86_64 Machine = 62 /* Advanced Micro Devices x86-64 */ - EM_AARCH64 Machine = 183 /* ARM 64-bit Architecture (AArch64) */ + EM_NONE Machine = 0 /* Unknown machine. */ + EM_M32 Machine = 1 /* AT&T WE32100. */ + EM_SPARC Machine = 2 /* Sun SPARC. */ + EM_386 Machine = 3 /* Intel i386. */ + EM_68K Machine = 4 /* Motorola 68000. */ + EM_88K Machine = 5 /* Motorola 88000. */ + EM_860 Machine = 7 /* Intel i860. */ + EM_MIPS Machine = 8 /* MIPS R3000 Big-Endian only. */ + EM_S370 Machine = 9 /* IBM System/370. */ + EM_MIPS_RS3_LE Machine = 10 /* MIPS R3000 Little-Endian. */ + EM_PARISC Machine = 15 /* HP PA-RISC. */ + EM_VPP500 Machine = 17 /* Fujitsu VPP500. */ + EM_SPARC32PLUS Machine = 18 /* SPARC v8plus. */ + EM_960 Machine = 19 /* Intel 80960. */ + EM_PPC Machine = 20 /* PowerPC 32-bit. */ + EM_PPC64 Machine = 21 /* PowerPC 64-bit. */ + EM_S390 Machine = 22 /* IBM System/390. */ + EM_V800 Machine = 36 /* NEC V800. */ + EM_FR20 Machine = 37 /* Fujitsu FR20. */ + EM_RH32 Machine = 38 /* TRW RH-32. */ + EM_RCE Machine = 39 /* Motorola RCE. */ + EM_ARM Machine = 40 /* ARM. */ + EM_SH Machine = 42 /* Hitachi SH. */ + EM_SPARCV9 Machine = 43 /* SPARC v9 64-bit. */ + EM_TRICORE Machine = 44 /* Siemens TriCore embedded processor. */ + EM_ARC Machine = 45 /* Argonaut RISC Core. */ + EM_H8_300 Machine = 46 /* Hitachi H8/300. */ + EM_H8_300H Machine = 47 /* Hitachi H8/300H. */ + EM_H8S Machine = 48 /* Hitachi H8S. */ + EM_H8_500 Machine = 49 /* Hitachi H8/500. */ + EM_IA_64 Machine = 50 /* Intel IA-64 Processor. */ + EM_MIPS_X Machine = 51 /* Stanford MIPS-X. */ + EM_COLDFIRE Machine = 52 /* Motorola ColdFire. */ + EM_68HC12 Machine = 53 /* Motorola M68HC12. */ + EM_MMA Machine = 54 /* Fujitsu MMA. */ + EM_PCP Machine = 55 /* Siemens PCP. */ + EM_NCPU Machine = 56 /* Sony nCPU. */ + EM_NDR1 Machine = 57 /* Denso NDR1 microprocessor. */ + EM_STARCORE Machine = 58 /* Motorola Star*Core processor. */ + EM_ME16 Machine = 59 /* Toyota ME16 processor. */ + EM_ST100 Machine = 60 /* STMicroelectronics ST100 processor. */ + EM_TINYJ Machine = 61 /* Advanced Logic Corp. TinyJ processor. */ + EM_X86_64 Machine = 62 /* Advanced Micro Devices x86-64 */ + EM_PDSP Machine = 63 /* Sony DSP Processor */ + EM_PDP10 Machine = 64 /* Digital Equipment Corp. PDP-10 */ + EM_PDP11 Machine = 65 /* Digital Equipment Corp. PDP-11 */ + EM_FX66 Machine = 66 /* Siemens FX66 microcontroller */ + EM_ST9PLUS Machine = 67 /* STMicroelectronics ST9+ 8/16 bit microcontroller */ + EM_ST7 Machine = 68 /* STMicroelectronics ST7 8-bit microcontroller */ + EM_68HC16 Machine = 69 /* Motorola MC68HC16 Microcontroller */ + EM_68HC11 Machine = 70 /* Motorola MC68HC11 Microcontroller */ + EM_68HC08 Machine = 71 /* Motorola MC68HC08 Microcontroller */ + EM_68HC05 Machine = 72 /* Motorola MC68HC05 Microcontroller */ + EM_SVX Machine = 73 /* Silicon Graphics SVx */ + EM_ST19 Machine = 74 /* STMicroelectronics ST19 8-bit microcontroller */ + EM_VAX Machine = 75 /* Digital VAX */ + EM_CRIS Machine = 76 /* Axis Communications 32-bit embedded processor */ + EM_JAVELIN Machine = 77 /* Infineon Technologies 32-bit embedded processor */ + EM_FIREPATH Machine = 78 /* Element 14 64-bit DSP Processor */ + EM_ZSP Machine = 79 /* LSI Logic 16-bit DSP Processor */ + EM_MMIX Machine = 80 /* Donald Knuth's educational 64-bit processor */ + EM_HUANY Machine = 81 /* Harvard University machine-independent object files */ + EM_PRISM Machine = 82 /* SiTera Prism */ + EM_AVR Machine = 83 /* Atmel AVR 8-bit microcontroller */ + EM_FR30 Machine = 84 /* Fujitsu FR30 */ + EM_D10V Machine = 85 /* Mitsubishi D10V */ + EM_D30V Machine = 86 /* Mitsubishi D30V */ + EM_V850 Machine = 87 /* NEC v850 */ + EM_M32R Machine = 88 /* Mitsubishi M32R */ + EM_MN10300 Machine = 89 /* Matsushita MN10300 */ + EM_MN10200 Machine = 90 /* Matsushita MN10200 */ + EM_PJ Machine = 91 /* picoJava */ + EM_OPENRISC Machine = 92 /* OpenRISC 32-bit embedded processor */ + EM_ARC_COMPACT Machine = 93 /* ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5) */ + EM_XTENSA Machine = 94 /* Tensilica Xtensa Architecture */ + EM_VIDEOCORE Machine = 95 /* Alphamosaic VideoCore processor */ + EM_TMM_GPP Machine = 96 /* Thompson Multimedia General Purpose Processor */ + EM_NS32K Machine = 97 /* National Semiconductor 32000 series */ + EM_TPC Machine = 98 /* Tenor Network TPC processor */ + EM_SNP1K Machine = 99 /* Trebia SNP 1000 processor */ + EM_ST200 Machine = 100 /* STMicroelectronics (www.st.com) ST200 microcontroller */ + EM_IP2K Machine = 101 /* Ubicom IP2xxx microcontroller family */ + EM_MAX Machine = 102 /* MAX Processor */ + EM_CR Machine = 103 /* National Semiconductor CompactRISC microprocessor */ + EM_F2MC16 Machine = 104 /* Fujitsu F2MC16 */ + EM_MSP430 Machine = 105 /* Texas Instruments embedded microcontroller msp430 */ + EM_BLACKFIN Machine = 106 /* Analog Devices Blackfin (DSP) processor */ + EM_SE_C33 Machine = 107 /* S1C33 Family of Seiko Epson processors */ + EM_SEP Machine = 108 /* Sharp embedded microprocessor */ + EM_ARCA Machine = 109 /* Arca RISC Microprocessor */ + EM_UNICORE Machine = 110 /* Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University */ + EM_EXCESS Machine = 111 /* eXcess: 16/32/64-bit configurable embedded CPU */ + EM_DXP Machine = 112 /* Icera Semiconductor Inc. Deep Execution Processor */ + EM_ALTERA_NIOS2 Machine = 113 /* Altera Nios II soft-core processor */ + EM_CRX Machine = 114 /* National Semiconductor CompactRISC CRX microprocessor */ + EM_XGATE Machine = 115 /* Motorola XGATE embedded processor */ + EM_C166 Machine = 116 /* Infineon C16x/XC16x processor */ + EM_M16C Machine = 117 /* Renesas M16C series microprocessors */ + EM_DSPIC30F Machine = 118 /* Microchip Technology dsPIC30F Digital Signal Controller */ + EM_CE Machine = 119 /* Freescale Communication Engine RISC core */ + EM_M32C Machine = 120 /* Renesas M32C series microprocessors */ + EM_TSK3000 Machine = 131 /* Altium TSK3000 core */ + EM_RS08 Machine = 132 /* Freescale RS08 embedded processor */ + EM_SHARC Machine = 133 /* Analog Devices SHARC family of 32-bit DSP processors */ + EM_ECOG2 Machine = 134 /* Cyan Technology eCOG2 microprocessor */ + EM_SCORE7 Machine = 135 /* Sunplus S+core7 RISC processor */ + EM_DSP24 Machine = 136 /* New Japan Radio (NJR) 24-bit DSP Processor */ + EM_VIDEOCORE3 Machine = 137 /* Broadcom VideoCore III processor */ + EM_LATTICEMICO32 Machine = 138 /* RISC processor for Lattice FPGA architecture */ + EM_SE_C17 Machine = 139 /* Seiko Epson C17 family */ + EM_TI_C6000 Machine = 140 /* The Texas Instruments TMS320C6000 DSP family */ + EM_TI_C2000 Machine = 141 /* The Texas Instruments TMS320C2000 DSP family */ + EM_TI_C5500 Machine = 142 /* The Texas Instruments TMS320C55x DSP family */ + EM_TI_ARP32 Machine = 143 /* Texas Instruments Application Specific RISC Processor, 32bit fetch */ + EM_TI_PRU Machine = 144 /* Texas Instruments Programmable Realtime Unit */ + EM_MMDSP_PLUS Machine = 160 /* STMicroelectronics 64bit VLIW Data Signal Processor */ + EM_CYPRESS_M8C Machine = 161 /* Cypress M8C microprocessor */ + EM_R32C Machine = 162 /* Renesas R32C series microprocessors */ + EM_TRIMEDIA Machine = 163 /* NXP Semiconductors TriMedia architecture family */ + EM_QDSP6 Machine = 164 /* QUALCOMM DSP6 Processor */ + EM_8051 Machine = 165 /* Intel 8051 and variants */ + EM_STXP7X Machine = 166 /* STMicroelectronics STxP7x family of configurable and extensible RISC processors */ + EM_NDS32 Machine = 167 /* Andes Technology compact code size embedded RISC processor family */ + EM_ECOG1 Machine = 168 /* Cyan Technology eCOG1X family */ + EM_ECOG1X Machine = 168 /* Cyan Technology eCOG1X family */ + EM_MAXQ30 Machine = 169 /* Dallas Semiconductor MAXQ30 Core Micro-controllers */ + EM_XIMO16 Machine = 170 /* New Japan Radio (NJR) 16-bit DSP Processor */ + EM_MANIK Machine = 171 /* M2000 Reconfigurable RISC Microprocessor */ + EM_CRAYNV2 Machine = 172 /* Cray Inc. NV2 vector architecture */ + EM_RX Machine = 173 /* Renesas RX family */ + EM_METAG Machine = 174 /* Imagination Technologies META processor architecture */ + EM_MCST_ELBRUS Machine = 175 /* MCST Elbrus general purpose hardware architecture */ + EM_ECOG16 Machine = 176 /* Cyan Technology eCOG16 family */ + EM_CR16 Machine = 177 /* National Semiconductor CompactRISC CR16 16-bit microprocessor */ + EM_ETPU Machine = 178 /* Freescale Extended Time Processing Unit */ + EM_SLE9X Machine = 179 /* Infineon Technologies SLE9X core */ + EM_L10M Machine = 180 /* Intel L10M */ + EM_K10M Machine = 181 /* Intel K10M */ + EM_AARCH64 Machine = 183 /* ARM 64-bit Architecture (AArch64) */ + EM_AVR32 Machine = 185 /* Atmel Corporation 32-bit microprocessor family */ + EM_STM8 Machine = 186 /* STMicroeletronics STM8 8-bit microcontroller */ + EM_TILE64 Machine = 187 /* Tilera TILE64 multicore architecture family */ + EM_TILEPRO Machine = 188 /* Tilera TILEPro multicore architecture family */ + EM_MICROBLAZE Machine = 189 /* Xilinx MicroBlaze 32-bit RISC soft processor core */ + EM_CUDA Machine = 190 /* NVIDIA CUDA architecture */ + EM_TILEGX Machine = 191 /* Tilera TILE-Gx multicore architecture family */ + EM_CLOUDSHIELD Machine = 192 /* CloudShield architecture family */ + EM_COREA_1ST Machine = 193 /* KIPO-KAIST Core-A 1st generation processor family */ + EM_COREA_2ND Machine = 194 /* KIPO-KAIST Core-A 2nd generation processor family */ + EM_ARC_COMPACT2 Machine = 195 /* Synopsys ARCompact V2 */ + EM_OPEN8 Machine = 196 /* Open8 8-bit RISC soft processor core */ + EM_RL78 Machine = 197 /* Renesas RL78 family */ + EM_VIDEOCORE5 Machine = 198 /* Broadcom VideoCore V processor */ + EM_78KOR Machine = 199 /* Renesas 78KOR family */ + EM_56800EX Machine = 200 /* Freescale 56800EX Digital Signal Controller (DSC) */ + EM_BA1 Machine = 201 /* Beyond BA1 CPU architecture */ + EM_BA2 Machine = 202 /* Beyond BA2 CPU architecture */ + EM_XCORE Machine = 203 /* XMOS xCORE processor family */ + EM_MCHP_PIC Machine = 204 /* Microchip 8-bit PIC(r) family */ + EM_INTEL205 Machine = 205 /* Reserved by Intel */ + EM_INTEL206 Machine = 206 /* Reserved by Intel */ + EM_INTEL207 Machine = 207 /* Reserved by Intel */ + EM_INTEL208 Machine = 208 /* Reserved by Intel */ + EM_INTEL209 Machine = 209 /* Reserved by Intel */ + EM_KM32 Machine = 210 /* KM211 KM32 32-bit processor */ + EM_KMX32 Machine = 211 /* KM211 KMX32 32-bit processor */ + EM_KMX16 Machine = 212 /* KM211 KMX16 16-bit processor */ + EM_KMX8 Machine = 213 /* KM211 KMX8 8-bit processor */ + EM_KVARC Machine = 214 /* KM211 KVARC processor */ + EM_CDP Machine = 215 /* Paneve CDP architecture family */ + EM_COGE Machine = 216 /* Cognitive Smart Memory Processor */ + EM_COOL Machine = 217 /* Bluechip Systems CoolEngine */ + EM_NORC Machine = 218 /* Nanoradio Optimized RISC */ + EM_CSR_KALIMBA Machine = 219 /* CSR Kalimba architecture family */ + EM_Z80 Machine = 220 /* Zilog Z80 */ + EM_VISIUM Machine = 221 /* Controls and Data Services VISIUMcore processor */ + EM_FT32 Machine = 222 /* FTDI Chip FT32 high performance 32-bit RISC architecture */ + EM_MOXIE Machine = 223 /* Moxie processor family */ + EM_AMDGPU Machine = 224 /* AMD GPU architecture */ + EM_RISCV Machine = 243 /* RISC-V */ + EM_LANAI Machine = 244 /* Lanai 32-bit processor */ + EM_BPF Machine = 247 /* Linux BPF – in-kernel virtual machine */ /* Non-standard or deprecated. */ EM_486 Machine = 6 /* Intel i486. */ @@ -289,6 +436,145 @@ var machineStrings = []intName{ {60, "EM_ST100"}, {61, "EM_TINYJ"}, {62, "EM_X86_64"}, + {63, "EM_PDSP"}, + {64, "EM_PDP10"}, + {65, "EM_PDP11"}, + {66, "EM_FX66"}, + {67, "EM_ST9PLUS"}, + {68, "EM_ST7"}, + {69, "EM_68HC16"}, + {70, "EM_68HC11"}, + {71, "EM_68HC08"}, + {72, "EM_68HC05"}, + {73, "EM_SVX"}, + {74, "EM_ST19"}, + {75, "EM_VAX"}, + {76, "EM_CRIS"}, + {77, "EM_JAVELIN"}, + {78, "EM_FIREPATH"}, + {79, "EM_ZSP"}, + {80, "EM_MMIX"}, + {81, "EM_HUANY"}, + {82, "EM_PRISM"}, + {83, "EM_AVR"}, + {84, "EM_FR30"}, + {85, "EM_D10V"}, + {86, "EM_D30V"}, + {87, "EM_V850"}, + {88, "EM_M32R"}, + {89, "EM_MN10300"}, + {90, "EM_MN10200"}, + {91, "EM_PJ"}, + {92, "EM_OPENRISC"}, + {93, "EM_ARC_COMPACT"}, + {94, "EM_XTENSA"}, + {95, "EM_VIDEOCORE"}, + {96, "EM_TMM_GPP"}, + {97, "EM_NS32K"}, + {98, "EM_TPC"}, + {99, "EM_SNP1K"}, + {100, "EM_ST200"}, + {101, "EM_IP2K"}, + {102, "EM_MAX"}, + {103, "EM_CR"}, + {104, "EM_F2MC16"}, + {105, "EM_MSP430"}, + {106, "EM_BLACKFIN"}, + {107, "EM_SE_C33"}, + {108, "EM_SEP"}, + {109, "EM_ARCA"}, + {110, "EM_UNICORE"}, + {111, "EM_EXCESS"}, + {112, "EM_DXP"}, + {113, "EM_ALTERA_NIOS2"}, + {114, "EM_CRX"}, + {115, "EM_XGATE"}, + {116, "EM_C166"}, + {117, "EM_M16C"}, + {118, "EM_DSPIC30F"}, + {119, "EM_CE"}, + {120, "EM_M32C"}, + {131, "EM_TSK3000"}, + {132, "EM_RS08"}, + {133, "EM_SHARC"}, + {134, "EM_ECOG2"}, + {135, "EM_SCORE7"}, + {136, "EM_DSP24"}, + {137, "EM_VIDEOCORE3"}, + {138, "EM_LATTICEMICO32"}, + {139, "EM_SE_C17"}, + {140, "EM_TI_C6000"}, + {141, "EM_TI_C2000"}, + {142, "EM_TI_C5500"}, + {143, "EM_TI_ARP32"}, + {144, "EM_TI_PRU"}, + {160, "EM_MMDSP_PLUS"}, + {161, "EM_CYPRESS_M8C"}, + {162, "EM_R32C"}, + {163, "EM_TRIMEDIA"}, + {164, "EM_QDSP6"}, + {165, "EM_8051"}, + {166, "EM_STXP7X"}, + {167, "EM_NDS32"}, + {168, "EM_ECOG1"}, + {168, "EM_ECOG1X"}, + {169, "EM_MAXQ30"}, + {170, "EM_XIMO16"}, + {171, "EM_MANIK"}, + {172, "EM_CRAYNV2"}, + {173, "EM_RX"}, + {174, "EM_METAG"}, + {175, "EM_MCST_ELBRUS"}, + {176, "EM_ECOG16"}, + {177, "EM_CR16"}, + {178, "EM_ETPU"}, + {179, "EM_SLE9X"}, + {180, "EM_L10M"}, + {181, "EM_K10M"}, + {183, "EM_AARCH64"}, + {185, "EM_AVR32"}, + {186, "EM_STM8"}, + {187, "EM_TILE64"}, + {188, "EM_TILEPRO"}, + {189, "EM_MICROBLAZE"}, + {190, "EM_CUDA"}, + {191, "EM_TILEGX"}, + {192, "EM_CLOUDSHIELD"}, + {193, "EM_COREA_1ST"}, + {194, "EM_COREA_2ND"}, + {195, "EM_ARC_COMPACT2"}, + {196, "EM_OPEN8"}, + {197, "EM_RL78"}, + {198, "EM_VIDEOCORE5"}, + {199, "EM_78KOR"}, + {200, "EM_56800EX"}, + {201, "EM_BA1"}, + {202, "EM_BA2"}, + {203, "EM_XCORE"}, + {204, "EM_MCHP_PIC"}, + {205, "EM_INTEL205"}, + {206, "EM_INTEL206"}, + {207, "EM_INTEL207"}, + {208, "EM_INTEL208"}, + {209, "EM_INTEL209"}, + {210, "EM_KM32"}, + {211, "EM_KMX32"}, + {212, "EM_KMX16"}, + {213, "EM_KMX8"}, + {214, "EM_KVARC"}, + {215, "EM_CDP"}, + {216, "EM_COGE"}, + {217, "EM_COOL"}, + {218, "EM_NORC"}, + {219, "EM_CSR_KALIMBA "}, + {220, "EM_Z80 "}, + {221, "EM_VISIUM "}, + {222, "EM_FT32 "}, + {223, "EM_MOXIE"}, + {224, "EM_AMDGPU"}, + {243, "EM_RISCV"}, + {244, "EM_LANAI"}, + {247, "EM_BPF"}, /* Non-standard or deprecated. */ {6, "EM_486"}, @@ -2081,6 +2367,124 @@ var rppc64Strings = []intName{ func (i R_PPC64) String() string { return stringName(uint32(i), rppc64Strings, false) } func (i R_PPC64) GoString() string { return stringName(uint32(i), rppc64Strings, true) } +// Relocation types for RISC-V processors. +type R_RISCV int + +const ( + R_RISCV_NONE R_RISCV = 0 /* No relocation. */ + R_RISCV_32 R_RISCV = 1 /* Add 32 bit zero extended symbol value */ + R_RISCV_64 R_RISCV = 2 /* Add 64 bit symbol value. */ + R_RISCV_RELATIVE R_RISCV = 3 /* Add load address of shared object. */ + R_RISCV_COPY R_RISCV = 4 /* Copy data from shared object. */ + R_RISCV_JUMP_SLOT R_RISCV = 5 /* Set GOT entry to code address. */ + R_RISCV_TLS_DTPMOD32 R_RISCV = 6 /* 32 bit ID of module containing symbol */ + R_RISCV_TLS_DTPMOD64 R_RISCV = 7 /* ID of module containing symbol */ + R_RISCV_TLS_DTPREL32 R_RISCV = 8 /* 32 bit relative offset in TLS block */ + R_RISCV_TLS_DTPREL64 R_RISCV = 9 /* Relative offset in TLS block */ + R_RISCV_TLS_TPREL32 R_RISCV = 10 /* 32 bit relative offset in static TLS block */ + R_RISCV_TLS_TPREL64 R_RISCV = 11 /* Relative offset in static TLS block */ + R_RISCV_BRANCH R_RISCV = 16 /* PC-relative branch */ + R_RISCV_JAL R_RISCV = 17 /* PC-relative jump */ + R_RISCV_CALL R_RISCV = 18 /* PC-relative call */ + R_RISCV_CALL_PLT R_RISCV = 19 /* PC-relative call (PLT) */ + R_RISCV_GOT_HI20 R_RISCV = 20 /* PC-relative GOT reference */ + R_RISCV_TLS_GOT_HI20 R_RISCV = 21 /* PC-relative TLS IE GOT offset */ + R_RISCV_TLS_GD_HI20 R_RISCV = 22 /* PC-relative TLS GD reference */ + R_RISCV_PCREL_HI20 R_RISCV = 23 /* PC-relative reference */ + R_RISCV_PCREL_LO12_I R_RISCV = 24 /* PC-relative reference */ + R_RISCV_PCREL_LO12_S R_RISCV = 25 /* PC-relative reference */ + R_RISCV_HI20 R_RISCV = 26 /* Absolute address */ + R_RISCV_LO12_I R_RISCV = 27 /* Absolute address */ + R_RISCV_LO12_S R_RISCV = 28 /* Absolute address */ + R_RISCV_TPREL_HI20 R_RISCV = 29 /* TLS LE thread offset */ + R_RISCV_TPREL_LO12_I R_RISCV = 30 /* TLS LE thread offset */ + R_RISCV_TPREL_LO12_S R_RISCV = 31 /* TLS LE thread offset */ + R_RISCV_TPREL_ADD R_RISCV = 32 /* TLS LE thread usage */ + R_RISCV_ADD8 R_RISCV = 33 /* 8-bit label addition */ + R_RISCV_ADD16 R_RISCV = 34 /* 16-bit label addition */ + R_RISCV_ADD32 R_RISCV = 35 /* 32-bit label addition */ + R_RISCV_ADD64 R_RISCV = 36 /* 64-bit label addition */ + R_RISCV_SUB8 R_RISCV = 37 /* 8-bit label subtraction */ + R_RISCV_SUB16 R_RISCV = 38 /* 16-bit label subtraction */ + R_RISCV_SUB32 R_RISCV = 39 /* 32-bit label subtraction */ + R_RISCV_SUB64 R_RISCV = 40 /* 64-bit label subtraction */ + R_RISCV_GNU_VTINHERIT R_RISCV = 41 /* GNU C++ vtable hierarchy */ + R_RISCV_GNU_VTENTRY R_RISCV = 42 /* GNU C++ vtable member usage */ + R_RISCV_ALIGN R_RISCV = 43 /* Alignment statement */ + R_RISCV_RVC_BRANCH R_RISCV = 44 /* PC-relative branch offset */ + R_RISCV_RVC_JUMP R_RISCV = 45 /* PC-relative jump offset */ + R_RISCV_RVC_LUI R_RISCV = 46 /* Absolute address */ + R_RISCV_GPREL_I R_RISCV = 47 /* GP-relative reference */ + R_RISCV_GPREL_S R_RISCV = 48 /* GP-relative reference */ + R_RISCV_TPREL_I R_RISCV = 49 /* TP-relative TLS LE load */ + R_RISCV_TPREL_S R_RISCV = 50 /* TP-relative TLS LE store */ + R_RISCV_RELAX R_RISCV = 51 /* Instruction pair can be relaxed */ + R_RISCV_SUB6 R_RISCV = 52 /* Local label subtraction */ + R_RISCV_SET6 R_RISCV = 53 /* Local label subtraction */ + R_RISCV_SET8 R_RISCV = 54 /* Local label subtraction */ + R_RISCV_SET16 R_RISCV = 55 /* Local label subtraction */ + R_RISCV_SET32 R_RISCV = 56 /* Local label subtraction */ +) + +var rriscvStrings = []intName{ + {0, "R_RISCV_NONE"}, + {1, "R_RISCV_32"}, + {2, "R_RISCV_64"}, + {3, "R_RISCV_RELATIVE"}, + {4, "R_RISCV_COPY"}, + {5, "R_RISCV_JUMP_SLOT"}, + {6, "R_RISCV_TLS_DTPMOD32"}, + {7, "R_RISCV_TLS_DTPMOD64"}, + {8, "R_RISCV_TLS_DTPREL32"}, + {9, "R_RISCV_TLS_DTPREL64"}, + {10, "R_RISCV_TLS_TPREL32"}, + {11, "R_RISCV_TLS_TPREL64"}, + {16, "R_RISCV_BRANCH"}, + {17, "R_RISCV_JAL"}, + {18, "R_RISCV_CALL"}, + {19, "R_RISCV_CALL_PLT"}, + {20, "R_RISCV_GOT_HI20"}, + {21, "R_RISCV_TLS_GOT_HI20"}, + {22, "R_RISCV_TLS_GD_HI20"}, + {23, "R_RISCV_PCREL_HI20"}, + {24, "R_RISCV_PCREL_LO12_I"}, + {25, "R_RISCV_PCREL_LO12_S"}, + {26, "R_RISCV_HI20"}, + {27, "R_RISCV_LO12_I"}, + {28, "R_RISCV_LO12_S"}, + {29, "R_RISCV_TPREL_HI20"}, + {30, "R_RISCV_TPREL_LO12_I"}, + {31, "R_RISCV_TPREL_LO12_S"}, + {32, "R_RISCV_TPREL_ADD"}, + {33, "R_RISCV_ADD8"}, + {34, "R_RISCV_ADD16"}, + {35, "R_RISCV_ADD32"}, + {36, "R_RISCV_ADD64"}, + {37, "R_RISCV_SUB8"}, + {38, "R_RISCV_SUB16"}, + {39, "R_RISCV_SUB32"}, + {40, "R_RISCV_SUB64"}, + {41, "R_RISCV_GNU_VTINHERIT"}, + {42, "R_RISCV_GNU_VTENTRY"}, + {43, "R_RISCV_ALIGN"}, + {44, "R_RISCV_RVC_BRANCH"}, + {45, "R_RISCV_RVC_JUMP"}, + {46, "R_RISCV_RVC_LUI"}, + {47, "R_RISCV_GPREL_I"}, + {48, "R_RISCV_GPREL_S"}, + {49, "R_RISCV_TPREL_I"}, + {50, "R_RISCV_TPREL_S"}, + {51, "R_RISCV_RELAX"}, + {52, "R_RISCV_SUB6"}, + {53, "R_RISCV_SET6"}, + {54, "R_RISCV_SET8"}, + {55, "R_RISCV_SET16"}, + {56, "R_RISCV_SET32"}, +} + +func (i R_RISCV) String() string { return stringName(uint32(i), rriscvStrings, false) } +func (i R_RISCV) GoString() string { return stringName(uint32(i), rriscvStrings, true) } + // Relocation types for s390x processors. type R_390 int diff --git a/libgo/go/debug/elf/file.go b/libgo/go/debug/elf/file.go index f28ae27cc01..bd6146437c9 100644 --- a/libgo/go/debug/elf/file.go +++ b/libgo/go/debug/elf/file.go @@ -609,6 +609,8 @@ func (f *File) applyRelocations(dst []byte, rels []byte) error { return f.applyRelocationsMIPS(dst, rels) case f.Class == ELFCLASS64 && f.Machine == EM_MIPS: return f.applyRelocationsMIPS64(dst, rels) + case f.Class == ELFCLASS64 && f.Machine == EM_RISCV: + return f.applyRelocationsRISCV64(dst, rels) case f.Class == ELFCLASS64 && f.Machine == EM_S390: return f.applyRelocationss390x(dst, rels) case f.Class == ELFCLASS32 && (f.Machine == EM_SPARC || f.Machine == EM_SPARC32PLUS): @@ -970,6 +972,55 @@ func (f *File) applyRelocationsMIPS64(dst []byte, rels []byte) error { return nil } +func (f *File) applyRelocationsRISCV64(dst []byte, rels []byte) error { + // 24 is the size of Rela64. + if len(rels)%24 != 0 { + return errors.New("length of relocation section is not a multiple of 24") + } + + symbols, _, err := f.getSymbols(SHT_SYMTAB) + if err != nil { + return err + } + + b := bytes.NewReader(rels) + var rela Rela64 + + for b.Len() > 0 { + binary.Read(b, f.ByteOrder, &rela) + symNo := rela.Info >> 32 + t := R_RISCV(rela.Info & 0xffff) + + if symNo == 0 || symNo > uint64(len(symbols)) { + continue + } + sym := &symbols[symNo-1] + switch SymType(sym.Info & 0xf) { + case STT_SECTION, STT_NOTYPE: + break + default: + continue + } + + switch t { + case R_RISCV_64: + if rela.Off+8 >= uint64(len(dst)) || rela.Addend < 0 { + continue + } + val := sym.Value + uint64(rela.Addend) + f.ByteOrder.PutUint64(dst[rela.Off:rela.Off+8], val) + case R_RISCV_32: + if rela.Off+4 >= uint64(len(dst)) || rela.Addend < 0 { + continue + } + val := uint32(sym.Value) + uint32(rela.Addend) + f.ByteOrder.PutUint32(dst[rela.Off:rela.Off+4], val) + } + } + + return nil +} + func (f *File) applyRelocationss390x(dst []byte, rels []byte) error { // 24 is the size of Rela64. if len(rels)%24 != 0 { @@ -1154,6 +1205,17 @@ func (f *File) applyRelocationsALPHA(dst []byte, rels []byte) error { } func (f *File) DWARF() (*dwarf.Data, error) { + dwarfSuffix := func(s *Section) string { + switch { + case strings.HasPrefix(s.Name, ".debug_"): + return s.Name[7:] + case strings.HasPrefix(s.Name, ".zdebug_"): + return s.Name[8:] + default: + return "" + } + + } // sectionData gets the data for s, checks its size, and // applies any applicable relations. sectionData := func(i int, s *Section) ([]byte, error) { @@ -1202,13 +1264,8 @@ func (f *File) DWARF() (*dwarf.Data, error) { // Don't bother loading others. var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil, "ranges": nil} for i, s := range f.Sections { - suffix := "" - switch { - case strings.HasPrefix(s.Name, ".debug_"): - suffix = s.Name[7:] - case strings.HasPrefix(s.Name, ".zdebug_"): - suffix = s.Name[8:] - default: + suffix := dwarfSuffix(s) + if suffix == "" { continue } if _, ok := dat[suffix]; !ok { @@ -1228,16 +1285,19 @@ func (f *File) DWARF() (*dwarf.Data, error) { // Look for DWARF4 .debug_types sections. for i, s := range f.Sections { - if s.Name == ".debug_types" { - b, err := sectionData(i, s) - if err != nil { - return nil, err - } + suffix := dwarfSuffix(s) + if suffix != "types" { + continue + } - err = d.AddTypes(fmt.Sprintf("types-%d", i), b) - if err != nil { - return nil, err - } + b, err := sectionData(i, s) + if err != nil { + return nil, err + } + + err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + if err != nil { + return nil, err } } diff --git a/libgo/go/debug/elf/file_test.go b/libgo/go/debug/elf/file_test.go index 58bdf277d36..11d8992b714 100644 --- a/libgo/go/debug/elf/file_test.go +++ b/libgo/go/debug/elf/file_test.go @@ -567,6 +567,25 @@ var relocationTests = []relocationTest{ }}, }, }, + { + "testdata/go-relocation-test-gcc720-riscv64.obj", + []relocationTestEntry{ + {0, &dwarf.Entry{ + Offset: 0xb, + Tag: dwarf.TagCompileUnit, + Children: true, + Field: []dwarf.Field{ + {Attr: dwarf.AttrProducer, Val: "GNU C11 7.2.0 -march=rv64imafdc -mabi=lp64d -g -gdwarf-2", Class: dwarf.ClassString}, + {Attr: dwarf.AttrLanguage, Val: int64(12), Class: dwarf.ClassConstant}, + {Attr: dwarf.AttrName, Val: "hello.c", Class: dwarf.ClassString}, + {Attr: dwarf.AttrCompDir, Val: "/tmp", Class: dwarf.ClassString}, + {Attr: dwarf.AttrLowpc, Val: uint64(0x0), Class: dwarf.ClassAddress}, + {Attr: dwarf.AttrHighpc, Val: uint64(0x2c), Class: dwarf.ClassAddress}, + {Attr: dwarf.AttrStmtList, Val: int64(0), Class: dwarf.ClassLinePtr}, + }, + }}, + }, + }, { "testdata/go-relocation-test-clang-x86.obj", []relocationTestEntry{ @@ -763,9 +782,10 @@ func TestCompressedSection(t *testing.T) { } func TestNoSectionOverlaps(t *testing.T) { - // Ensure 6l outputs sections without overlaps. - if runtime.GOOS != "linux" && runtime.GOOS != "freebsd" { - return // not ELF + // Ensure cmd/link outputs sections without overlaps. + switch runtime.GOOS { + case "android", "darwin", "js", "nacl", "plan9", "windows": + t.Skipf("cmd/link doesn't produce ELF binaries on %s", runtime.GOOS) } _ = net.ResolveIPAddr // force dynamic linkage f, err := Open(os.Args[0]) diff --git a/libgo/go/debug/elf/testdata/go-relocation-test-gcc720-riscv64.obj b/libgo/go/debug/elf/testdata/go-relocation-test-gcc720-riscv64.obj new file mode 100644 index 00000000000..91ae6487a3a Binary files /dev/null and b/libgo/go/debug/elf/testdata/go-relocation-test-gcc720-riscv64.obj differ diff --git a/libgo/go/debug/gosym/pclntab.go b/libgo/go/debug/gosym/pclntab.go index ba1cf8b699a..ad99b4dc5a6 100644 --- a/libgo/go/debug/gosym/pclntab.go +++ b/libgo/go/debug/gosym/pclntab.go @@ -9,6 +9,7 @@ package gosym import ( + "bytes" "encoding/binary" "sync" ) @@ -42,6 +43,7 @@ type LineTable struct { filetab []byte nfiletab uint32 fileMap map[string]uint32 + strings map[uint32]string // interned substrings of Data, keyed by offset } // NOTE(rsc): This is wrong for GOARCH=arm, which uses a quantum of 4, @@ -120,7 +122,7 @@ func (t *LineTable) LineToPC(line int, maxpc uint64) uint64 { // Text must be the start address of the // corresponding text segment. func NewLineTable(data []byte, text uint64) *LineTable { - return &LineTable{Data: data, PC: text, Line: 0} + return &LineTable{Data: data, PC: text, Line: 0, strings: make(map[uint32]string)} } // Go 1.2 symbol table format. @@ -266,11 +268,13 @@ func (t *LineTable) readvarint(pp *[]byte) uint32 { // string returns a Go string found at off. func (t *LineTable) string(off uint32) string { - for i := off; ; i++ { - if t.Data[i] == 0 { - return string(t.Data[off:i]) - } + if s, ok := t.strings[off]; ok { + return s } + i := bytes.IndexByte(t.Data[off:], 0) + s := string(t.Data[off : off+uint32(i)]) + t.strings[off] = s + return s } // step advances to the next pc, value pair in the encoded table. diff --git a/libgo/go/debug/macho/file.go b/libgo/go/debug/macho/file.go index 7b9e83e5a87..16708e5247f 100644 --- a/libgo/go/debug/macho/file.go +++ b/libgo/go/debug/macho/file.go @@ -9,11 +9,13 @@ package macho import ( "bytes" + "compress/zlib" "debug/dwarf" "encoding/binary" "fmt" "io" "os" + "strings" ) // A File represents an open Mach-O file. @@ -545,8 +547,9 @@ func (f *File) pushSection(sh *Section, r io.ReaderAt) error { } func cstring(b []byte) string { - var i int - for i = 0; i < len(b) && b[i] != 0; i++ { + i := bytes.IndexByte(b, 0) + if i == -1 { + i = len(b) } return string(b[0:i]) } @@ -574,26 +577,84 @@ func (f *File) Section(name string) *Section { // DWARF returns the DWARF debug information for the Mach-O file. func (f *File) DWARF() (*dwarf.Data, error) { - // There are many other DWARF sections, but these - // are the ones the debug/dwarf package uses. - // Don't bother loading others. - var names = [...]string{"abbrev", "info", "line", "ranges", "str"} - var dat [len(names)][]byte - for i, name := range names { - name = "__debug_" + name - s := f.Section(name) - if s == nil { - continue + dwarfSuffix := func(s *Section) string { + switch { + case strings.HasPrefix(s.Name, "__debug_"): + return s.Name[8:] + case strings.HasPrefix(s.Name, "__zdebug_"): + return s.Name[9:] + default: + return "" } + + } + sectionData := func(s *Section) ([]byte, error) { b, err := s.Data() if err != nil && uint64(len(b)) < s.Size { return nil, err } - dat[i] = b + + if len(b) >= 12 && string(b[:4]) == "ZLIB" { + dlen := binary.BigEndian.Uint64(b[4:12]) + dbuf := make([]byte, dlen) + r, err := zlib.NewReader(bytes.NewBuffer(b[12:])) + if err != nil { + return nil, err + } + if _, err := io.ReadFull(r, dbuf); err != nil { + return nil, err + } + if err := r.Close(); err != nil { + return nil, err + } + b = dbuf + } + return b, nil } - abbrev, info, line, ranges, str := dat[0], dat[1], dat[2], dat[3], dat[4] - return dwarf.New(abbrev, nil, nil, info, line, nil, ranges, str) + // There are many other DWARF sections, but these + // are the ones the debug/dwarf package uses. + // Don't bother loading others. + var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil, "ranges": nil} + for _, s := range f.Sections { + suffix := dwarfSuffix(s) + if suffix == "" { + continue + } + if _, ok := dat[suffix]; !ok { + continue + } + b, err := sectionData(s) + if err != nil { + return nil, err + } + dat[suffix] = b + } + + d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, dat["ranges"], dat["str"]) + if err != nil { + return nil, err + } + + // Look for DWARF4 .debug_types sections. + for i, s := range f.Sections { + suffix := dwarfSuffix(s) + if suffix != "types" { + continue + } + + b, err := sectionData(s) + if err != nil { + return nil, err + } + + err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + if err != nil { + return nil, err + } + } + + return d, nil } // ImportedSymbols returns the names of all symbols diff --git a/libgo/go/debug/macho/macho.go b/libgo/go/debug/macho/macho.go index fed8eb25a43..7bc1950bfdb 100644 --- a/libgo/go/debug/macho/macho.go +++ b/libgo/go/debug/macho/macho.go @@ -60,6 +60,7 @@ const ( Cpu386 Cpu = 7 CpuAmd64 Cpu = Cpu386 | cpuArch64 CpuArm Cpu = 12 + CpuArm64 Cpu = CpuArm | cpuArch64 CpuPpc Cpu = 18 CpuPpc64 Cpu = CpuPpc | cpuArch64 ) @@ -68,6 +69,7 @@ var cpuStrings = []intName{ {uint32(Cpu386), "Cpu386"}, {uint32(CpuAmd64), "CpuAmd64"}, {uint32(CpuArm), "CpuArm"}, + {uint32(CpuArm64), "CpuArm64"}, {uint32(CpuPpc), "CpuPpc"}, {uint32(CpuPpc64), "CpuPpc64"}, } diff --git a/libgo/go/debug/macho/reloctype_string.go b/libgo/go/debug/macho/reloctype_string.go index 6d5c5d87e82..9c2b13186e7 100644 --- a/libgo/go/debug/macho/reloctype_string.go +++ b/libgo/go/debug/macho/reloctype_string.go @@ -2,7 +2,7 @@ package macho -import "fmt" +import "strconv" const _RelocTypeGeneric_name = "GENERIC_RELOC_VANILLAGENERIC_RELOC_PAIRGENERIC_RELOC_SECTDIFFGENERIC_RELOC_PB_LA_PTRGENERIC_RELOC_LOCAL_SECTDIFFGENERIC_RELOC_TLV" @@ -10,7 +10,7 @@ var _RelocTypeGeneric_index = [...]uint8{0, 21, 39, 61, 84, 112, 129} func (i RelocTypeGeneric) String() string { if i < 0 || i >= RelocTypeGeneric(len(_RelocTypeGeneric_index)-1) { - return fmt.Sprintf("RelocTypeGeneric(%d)", i) + return "RelocTypeGeneric(" + strconv.FormatInt(int64(i), 10) + ")" } return _RelocTypeGeneric_name[_RelocTypeGeneric_index[i]:_RelocTypeGeneric_index[i+1]] } @@ -21,7 +21,7 @@ var _RelocTypeX86_64_index = [...]uint8{0, 21, 40, 59, 80, 96, 119, 140, 161, 18 func (i RelocTypeX86_64) String() string { if i < 0 || i >= RelocTypeX86_64(len(_RelocTypeX86_64_index)-1) { - return fmt.Sprintf("RelocTypeX86_64(%d)", i) + return "RelocTypeX86_64(" + strconv.FormatInt(int64(i), 10) + ")" } return _RelocTypeX86_64_name[_RelocTypeX86_64_index[i]:_RelocTypeX86_64_index[i+1]] } @@ -32,7 +32,7 @@ var _RelocTypeARM_index = [...]uint8{0, 17, 31, 49, 73, 92, 106, 126, 148, 162, func (i RelocTypeARM) String() string { if i < 0 || i >= RelocTypeARM(len(_RelocTypeARM_index)-1) { - return fmt.Sprintf("RelocTypeARM(%d)", i) + return "RelocTypeARM(" + strconv.FormatInt(int64(i), 10) + ")" } return _RelocTypeARM_name[_RelocTypeARM_index[i]:_RelocTypeARM_index[i+1]] } @@ -43,7 +43,7 @@ var _RelocTypeARM64_index = [...]uint16{0, 20, 42, 62, 80, 101, 128, 158, 184, 2 func (i RelocTypeARM64) String() string { if i < 0 || i >= RelocTypeARM64(len(_RelocTypeARM64_index)-1) { - return fmt.Sprintf("RelocTypeARM64(%d)", i) + return "RelocTypeARM64(" + strconv.FormatInt(int64(i), 10) + ")" } return _RelocTypeARM64_name[_RelocTypeARM64_index[i]:_RelocTypeARM64_index[i+1]] } diff --git a/libgo/go/debug/pe/file.go b/libgo/go/debug/pe/file.go index 87f225cb398..2f5efae4e67 100644 --- a/libgo/go/debug/pe/file.go +++ b/libgo/go/debug/pe/file.go @@ -6,11 +6,14 @@ package pe import ( + "bytes" + "compress/zlib" "debug/dwarf" "encoding/binary" "fmt" "io" "os" + "strings" ) // Avoid use of post-Go 1.4 io features, to make safe for toolchain bootstrap. @@ -217,29 +220,91 @@ func (f *File) Section(name string) *Section { } func (f *File) DWARF() (*dwarf.Data, error) { - // There are many other DWARF sections, but these - // are the ones the debug/dwarf package uses. - // Don't bother loading others. - var names = [...]string{"abbrev", "info", "line", "ranges", "str"} - var dat [len(names)][]byte - for i, name := range names { - name = ".debug_" + name - s := f.Section(name) - if s == nil { - continue + dwarfSuffix := func(s *Section) string { + switch { + case strings.HasPrefix(s.Name, ".debug_"): + return s.Name[7:] + case strings.HasPrefix(s.Name, ".zdebug_"): + return s.Name[8:] + default: + return "" } + + } + + // sectionData gets the data for s and checks its size. + sectionData := func(s *Section) ([]byte, error) { b, err := s.Data() if err != nil && uint32(len(b)) < s.Size { return nil, err } + if 0 < s.VirtualSize && s.VirtualSize < s.Size { b = b[:s.VirtualSize] } - dat[i] = b + + if len(b) >= 12 && string(b[:4]) == "ZLIB" { + dlen := binary.BigEndian.Uint64(b[4:12]) + dbuf := make([]byte, dlen) + r, err := zlib.NewReader(bytes.NewBuffer(b[12:])) + if err != nil { + return nil, err + } + if _, err := io.ReadFull(r, dbuf); err != nil { + return nil, err + } + if err := r.Close(); err != nil { + return nil, err + } + b = dbuf + } + return b, nil } - abbrev, info, line, ranges, str := dat[0], dat[1], dat[2], dat[3], dat[4] - return dwarf.New(abbrev, nil, nil, info, line, nil, ranges, str) + // There are many other DWARF sections, but these + // are the ones the debug/dwarf package uses. + // Don't bother loading others. + var dat = map[string][]byte{"abbrev": nil, "info": nil, "str": nil, "line": nil, "ranges": nil} + for _, s := range f.Sections { + suffix := dwarfSuffix(s) + if suffix == "" { + continue + } + if _, ok := dat[suffix]; !ok { + continue + } + + b, err := sectionData(s) + if err != nil { + return nil, err + } + dat[suffix] = b + } + + d, err := dwarf.New(dat["abbrev"], nil, nil, dat["info"], dat["line"], nil, dat["ranges"], dat["str"]) + if err != nil { + return nil, err + } + + // Look for DWARF4 .debug_types sections. + for i, s := range f.Sections { + suffix := dwarfSuffix(s) + if suffix != "types" { + continue + } + + b, err := sectionData(s) + if err != nil { + return nil, err + } + + err = d.AddTypes(fmt.Sprintf("types-%d", i), b) + if err != nil { + return nil, err + } + } + + return d, nil } // TODO(brainman): document ImportDirectory once we decide what to do with it. @@ -260,19 +325,59 @@ type ImportDirectory struct { // It does not return weak symbols. func (f *File) ImportedSymbols() ([]string, error) { pe64 := f.Machine == IMAGE_FILE_MACHINE_AMD64 - ds := f.Section(".idata") - if ds == nil { - // not dynamic, so no libraries + + // grab the number of data directory entries + var dd_length uint32 + if pe64 { + dd_length = f.OptionalHeader.(*OptionalHeader64).NumberOfRvaAndSizes + } else { + dd_length = f.OptionalHeader.(*OptionalHeader32).NumberOfRvaAndSizes + } + + // check that the length of data directory entries is large + // enough to include the imports directory. + if dd_length < IMAGE_DIRECTORY_ENTRY_IMPORT+1 { return nil, nil } + + // grab the import data directory entry + var idd DataDirectory + if pe64 { + idd = f.OptionalHeader.(*OptionalHeader64).DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + } else { + idd = f.OptionalHeader.(*OptionalHeader32).DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] + } + + // figure out which section contains the import directory table + var ds *Section + ds = nil + for _, s := range f.Sections { + if s.VirtualAddress <= idd.VirtualAddress && idd.VirtualAddress < s.VirtualAddress+s.VirtualSize { + ds = s + break + } + } + + // didn't find a section, so no import libraries were found + if ds == nil { + return nil, nil + } + d, err := ds.Data() if err != nil { return nil, err } + + // seek to the virtual address specified in the import data directory + d = d[idd.VirtualAddress-ds.VirtualAddress:] + + // start decoding the import directory var ida []ImportDirectory for len(d) > 0 { var dt ImportDirectory dt.OriginalFirstThunk = binary.LittleEndian.Uint32(d[0:4]) + dt.TimeDateStamp = binary.LittleEndian.Uint32(d[4:8]) + dt.ForwarderChain = binary.LittleEndian.Uint32(d[8:12]) dt.Name = binary.LittleEndian.Uint32(d[12:16]) dt.FirstThunk = binary.LittleEndian.Uint32(d[16:20]) d = d[20:] @@ -282,7 +387,7 @@ func (f *File) ImportedSymbols() ([]string, error) { ida = append(ida, dt) } // TODO(brainman): this needs to be rewritten - // ds.Data() return contets of .idata section. Why store in variable called "names"? + // ds.Data() returns contents of section containing import table. Why store in variable called "names"? // Why we are retrieving it second time? We already have it in "d", and it is not modified anywhere. // getString does not extracts a string from symbol string table (as getString doco says). // Why ds.Data() called again and again in the loop? diff --git a/libgo/go/debug/pe/file_test.go b/libgo/go/debug/pe/file_test.go index 8645d676b75..24cd673254e 100644 --- a/libgo/go/debug/pe/file_test.go +++ b/libgo/go/debug/pe/file_test.go @@ -532,3 +532,31 @@ func TestBuildingWindowsGUI(t *testing.T) { t.Fatalf("unexpected OptionalHeader type: have %T, but want *pe.OptionalHeader32 or *pe.OptionalHeader64", oh) } } + +func TestImportTableInUnknownSection(t *testing.T) { + if runtime.GOOS != "windows" { + t.Skip("skipping windows only test") + } + + // first we need to find this font driver + path, err := exec.LookPath("atmfd.dll") + if err != nil { + t.Fatalf("unable to locate required file %q in search path: %s", "atmfd.dll", err) + } + + f, err := Open(path) + if err != nil { + t.Error(err) + } + defer f.Close() + + // now we can extract its imports + symbols, err := f.ImportedSymbols() + if err != nil { + t.Error(err) + } + + if len(symbols) == 0 { + t.Fatalf("unable to locate any imported symbols within file %q.", path) + } +} diff --git a/libgo/go/debug/pe/pe.go b/libgo/go/debug/pe/pe.go index 8050d59c70d..e933ae1c2aa 100644 --- a/libgo/go/debug/pe/pe.go +++ b/libgo/go/debug/pe/pe.go @@ -91,6 +91,7 @@ const ( IMAGE_FILE_MACHINE_AM33 = 0x1d3 IMAGE_FILE_MACHINE_AMD64 = 0x8664 IMAGE_FILE_MACHINE_ARM = 0x1c0 + IMAGE_FILE_MACHINE_ARM64 = 0xaa64 IMAGE_FILE_MACHINE_EBC = 0xebc IMAGE_FILE_MACHINE_I386 = 0x14c IMAGE_FILE_MACHINE_IA64 = 0x200 @@ -108,3 +109,22 @@ const ( IMAGE_FILE_MACHINE_THUMB = 0x1c2 IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x169 ) + +// IMAGE_DIRECTORY_ENTRY constants +const ( + IMAGE_DIRECTORY_ENTRY_EXPORT = 0 + IMAGE_DIRECTORY_ENTRY_IMPORT = 1 + IMAGE_DIRECTORY_ENTRY_RESOURCE = 2 + IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 + IMAGE_DIRECTORY_ENTRY_SECURITY = 4 + IMAGE_DIRECTORY_ENTRY_BASERELOC = 5 + IMAGE_DIRECTORY_ENTRY_DEBUG = 6 + IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7 + IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8 + IMAGE_DIRECTORY_ENTRY_TLS = 9 + IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10 + IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11 + IMAGE_DIRECTORY_ENTRY_IAT = 12 + IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13 + IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14 +) diff --git a/libgo/go/debug/pe/string.go b/libgo/go/debug/pe/string.go index c30255f341a..cab0366ade2 100644 --- a/libgo/go/debug/pe/string.go +++ b/libgo/go/debug/pe/string.go @@ -5,6 +5,7 @@ package pe import ( + "bytes" "encoding/binary" "fmt" "io" @@ -13,8 +14,9 @@ import ( // cstring converts ASCII byte sequence b to string. // It stops once it finds 0 or reaches end of b. func cstring(b []byte) string { - var i int - for i = 0; i < len(b) && b[i] != 0; i++ { + i := bytes.IndexByte(b, 0) + if i == -1 { + i = len(b) } return string(b[:i]) } diff --git a/libgo/go/encoding/asn1/asn1.go b/libgo/go/encoding/asn1/asn1.go index 26868a3bd7f..1ed357adfff 100644 --- a/libgo/go/encoding/asn1/asn1.go +++ b/libgo/go/encoding/asn1/asn1.go @@ -250,7 +250,7 @@ func (oi ObjectIdentifier) String() string { // parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and // returns it. An object identifier is a sequence of variable length integers // that are assigned in a hierarchy. -func parseObjectIdentifier(bytes []byte) (s []int, err error) { +func parseObjectIdentifier(bytes []byte) (s ObjectIdentifier, err error) { if len(bytes) == 0 { err = SyntaxError{"zero length OBJECT IDENTIFIER"} return @@ -793,6 +793,12 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam matchAnyClassAndTag = false } + if !params.explicit && params.private && params.tag != nil { + expectedClass = ClassPrivate + expectedTag = *params.tag + matchAnyClassAndTag = false + } + // We have unwrapped any explicit tagging at this point. if !matchAnyClassAndTag && (t.class != expectedClass || t.tag != expectedTag) || (!matchAny && t.isCompound != compoundType) { @@ -1028,6 +1034,7 @@ func setDefaultValue(v reflect.Value, params fieldParameters) (ok bool) { // The following tags on struct fields have special meaning to Unmarshal: // // application specifies that an APPLICATION tag is used +// private specifies that a PRIVATE tag is used // default:x sets the default value for optional integer fields (only used if optional is also present) // explicit specifies that an additional, explicit tag wraps the implicit one // optional marks the field as ASN.1 OPTIONAL diff --git a/libgo/go/encoding/asn1/asn1_test.go b/libgo/go/encoding/asn1/asn1_test.go index 5e67dc5ee4d..f0a54e0cb2e 100644 --- a/libgo/go/encoding/asn1/asn1_test.go +++ b/libgo/go/encoding/asn1/asn1_test.go @@ -227,7 +227,7 @@ func TestBitStringRightAlign(t *testing.T) { type objectIdentifierTest struct { in []byte ok bool - out []int + out ObjectIdentifier // has base type[]int } var objectIdentifierTestData = []objectIdentifierTest{ @@ -428,11 +428,12 @@ var parseFieldParametersTestData []parseFieldParametersTest = []parseFieldParame {"optional", fieldParameters{optional: true}}, {"explicit", fieldParameters{explicit: true, tag: new(int)}}, {"application", fieldParameters{application: true, tag: new(int)}}, + {"private", fieldParameters{private: true, tag: new(int)}}, {"optional,explicit", fieldParameters{optional: true, explicit: true, tag: new(int)}}, {"default:42", fieldParameters{defaultValue: newInt64(42)}}, {"tag:17", fieldParameters{tag: newInt(17)}}, {"optional,explicit,default:42,tag:17", fieldParameters{optional: true, explicit: true, defaultValue: newInt64(42), tag: newInt(17)}}, - {"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{true, true, false, newInt64(42), newInt(17), 0, 0, false, false}}, + {"optional,explicit,default:42,tag:17,rubbish1", fieldParameters{optional: true, explicit: true, application: false, defaultValue: newInt64(42), tag: newInt(17), stringType: 0, timeType: 0, set: false, omitEmpty: false}}, {"set", fieldParameters{set: true}}, } @@ -1079,6 +1080,7 @@ func TestTaggedRawValue(t *testing.T) { {true, []byte{0x30, 3, (ClassContextSpecific << 6) | tag, 1, 1}}, {true, []byte{0x30, 3, (ClassContextSpecific << 6) | tag | isCompound, 1, 1}}, {false, []byte{0x30, 3, (ClassApplication << 6) | tag | isCompound, 1, 1}}, + {false, []byte{0x30, 3, (ClassPrivate << 6) | tag | isCompound, 1, 1}}, } for i, test := range tests { diff --git a/libgo/go/encoding/asn1/common.go b/libgo/go/encoding/asn1/common.go index a6589a521af..255d1ebfa89 100644 --- a/libgo/go/encoding/asn1/common.go +++ b/libgo/go/encoding/asn1/common.go @@ -75,6 +75,7 @@ type fieldParameters struct { optional bool // true iff the field is OPTIONAL explicit bool // true iff an EXPLICIT tag is in use. application bool // true iff an APPLICATION tag is in use. + private bool // true iff a PRIVATE tag is in use. defaultValue *int64 // a default value for INTEGER typed fields (maybe nil). tag *int // the EXPLICIT or IMPLICIT tag (maybe nil). stringType int // the string tag to use when marshaling. @@ -130,6 +131,11 @@ func parseFieldParameters(str string) (ret fieldParameters) { if ret.tag == nil { ret.tag = new(int) } + case part == "private": + ret.private = true + if ret.tag == nil { + ret.tag = new(int) + } case part == "omitempty": ret.omitEmpty = true } diff --git a/libgo/go/encoding/asn1/marshal.go b/libgo/go/encoding/asn1/marshal.go index 3e85651ffd0..c9ae2ca33e5 100644 --- a/libgo/go/encoding/asn1/marshal.go +++ b/libgo/go/encoding/asn1/marshal.go @@ -631,6 +631,8 @@ func makeField(v reflect.Value, params fieldParameters) (e encoder, err error) { if params.tag != nil { if params.application { class = ClassApplication + } else if params.private { + class = ClassPrivate } else { class = ClassContextSpecific } diff --git a/libgo/go/encoding/asn1/marshal_test.go b/libgo/go/encoding/asn1/marshal_test.go index 4f755a1f39f..a77826a7b03 100644 --- a/libgo/go/encoding/asn1/marshal_test.go +++ b/libgo/go/encoding/asn1/marshal_test.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/hex" "math/big" + "reflect" "strings" "testing" "time" @@ -80,6 +81,13 @@ type applicationTest struct { B int `asn1:"application,tag:1,explicit"` } +type privateTest struct { + A int `asn1:"private,tag:0"` + B int `asn1:"private,tag:1,explicit"` + C int `asn1:"private,tag:31"` // tag size should be 2 octet + D int `asn1:"private,tag:128"` // tag size should be 3 octet +} + type numericStringTest struct { A string `asn1:"numeric"` } @@ -169,6 +177,7 @@ var marshalTests = []marshalTest{ {defaultTest{1}, "3000"}, {defaultTest{2}, "3003020102"}, {applicationTest{1, 2}, "30084001016103020102"}, + {privateTest{1, 2, 3, 4}, "3011c00101e103020102df1f0103df81000104"}, {numericStringTest{"1 9"}, "30051203312039"}, } @@ -195,6 +204,7 @@ type marshalWithParamsTest struct { var marshalWithParamsTests = []marshalWithParamsTest{ {intStruct{10}, "set", "310302010a"}, {intStruct{10}, "application", "600302010a"}, + {intStruct{10}, "private", "e00302010a"}, } func TestMarshalWithParams(t *testing.T) { @@ -244,6 +254,62 @@ func TestInvalidUTF8(t *testing.T) { } } +func TestMarshalOID(t *testing.T) { + var marshalTestsOID = []marshalTest{ + {[]byte("\x06\x01\x30"), "0403060130"}, // bytes format returns a byte sequence \x04 + // {ObjectIdentifier([]int{0}), "060100"}, // returns an error as OID 0.0 has the same encoding + {[]byte("\x06\x010"), "0403060130"}, // same as above "\x06\x010" = "\x06\x01" + "0" + {ObjectIdentifier([]int{2, 999, 3}), "0603883703"}, // Example of ITU-T X.690 + {ObjectIdentifier([]int{0, 0}), "060100"}, // zero OID + } + for i, test := range marshalTestsOID { + data, err := Marshal(test.in) + if err != nil { + t.Errorf("#%d failed: %s", i, err) + } + out, _ := hex.DecodeString(test.out) + if !bytes.Equal(out, data) { + t.Errorf("#%d got: %x want %x\n\t%q\n\t%q", i, data, out, data, out) + } + } +} + +func TestIssue11130(t *testing.T) { + data := []byte("\x06\x010") // == \x06\x01\x30 == OID = 0 (the figure) + var v interface{} + // v has Zero value here and Elem() would panic + _, err := Unmarshal(data, &v) + if err != nil { + t.Errorf("%v", err) + return + } + if reflect.TypeOf(v).String() != reflect.TypeOf(ObjectIdentifier{}).String() { + t.Errorf("marshal OID returned an invalid type") + return + } + + data1, err := Marshal(v) + if err != nil { + t.Errorf("%v", err) + return + } + + if !bytes.Equal(data, data1) { + t.Errorf("got: %q, want: %q \n", data1, data) + return + } + + var v1 interface{} + _, err = Unmarshal(data1, &v1) + if err != nil { + t.Errorf("%v", err) + return + } + if !reflect.DeepEqual(v, v1) { + t.Errorf("got: %#v data=%q , want : %#v data=%q\n ", v1, data1, v, data) + } +} + func BenchmarkMarshal(b *testing.B) { b.ReportAllocs() diff --git a/libgo/go/encoding/base32/base32.go b/libgo/go/encoding/base32/base32.go index e72ba74983e..3fb6caceab4 100644 --- a/libgo/go/encoding/base32/base32.go +++ b/libgo/go/encoding/base32/base32.go @@ -21,7 +21,7 @@ import ( // introduced for SASL GSSAPI and standardized in RFC 4648. // The alternate "base32hex" encoding is used in DNSSEC. type Encoding struct { - encode string + encode [32]byte decodeMap [256]byte padChar rune } @@ -37,8 +37,12 @@ const encodeHex = "0123456789ABCDEFGHIJKLMNOPQRSTUV" // NewEncoding returns a new Encoding defined by the given alphabet, // which must be a 32-byte string. func NewEncoding(encoder string) *Encoding { + if len(encoder) != 32 { + panic("encoding alphabet is not 32-bytes long") + } + e := new(Encoding) - e.encode = encoder + copy(e.encode[:], encoder) e.padChar = StdPadding for i := 0; i < len(e.decodeMap); i++ { @@ -96,10 +100,6 @@ func (enc Encoding) WithPadding(padding rune) *Encoding { // so Encode is not appropriate for use on individual blocks // of a large data stream. Use NewEncoder() instead. func (enc *Encoding) Encode(dst, src []byte) { - if len(src) == 0 { - return - } - for len(src) > 0 { var b [8]byte @@ -133,17 +133,17 @@ func (enc *Encoding) Encode(dst, src []byte) { size := len(dst) if size >= 8 { // Common case, unrolled for extra performance - dst[0] = enc.encode[b[0]] - dst[1] = enc.encode[b[1]] - dst[2] = enc.encode[b[2]] - dst[3] = enc.encode[b[3]] - dst[4] = enc.encode[b[4]] - dst[5] = enc.encode[b[5]] - dst[6] = enc.encode[b[6]] - dst[7] = enc.encode[b[7]] + dst[0] = enc.encode[b[0]&31] + dst[1] = enc.encode[b[1]&31] + dst[2] = enc.encode[b[2]&31] + dst[3] = enc.encode[b[3]&31] + dst[4] = enc.encode[b[4]&31] + dst[5] = enc.encode[b[5]&31] + dst[6] = enc.encode[b[6]&31] + dst[7] = enc.encode[b[7]&31] } else { for i := 0; i < size; i++ { - dst[i] = enc.encode[b[i]] + dst[i] = enc.encode[b[i]&31] } } @@ -244,8 +244,9 @@ func (e *encoder) Close() error { // If there's anything left in the buffer, flush it out if e.err == nil && e.nbuf > 0 { e.enc.Encode(e.out[0:], e.buf[0:e.nbuf]) + encodedLen := e.enc.EncodedLen(e.nbuf) e.nbuf = 0 - _, e.err = e.w.Write(e.out[0:8]) + _, e.err = e.w.Write(e.out[0:encodedLen]) } return e.err } @@ -403,15 +404,22 @@ type decoder struct { outbuf [1024 / 8 * 5]byte } -func readEncodedData(r io.Reader, buf []byte, min int) (n int, err error) { +func readEncodedData(r io.Reader, buf []byte, min int, expectsPadding bool) (n int, err error) { for n < min && err == nil { var nn int nn, err = r.Read(buf[n:]) n += nn } + // data was read, less than min bytes could be read if n < min && n > 0 && err == io.EOF { err = io.ErrUnexpectedEOF } + // no data was read, the buffer already contains some data + // when padding is disabled this is not an error, as the message can be of + // any length + if expectsPadding && min < 8 && n == 0 && err == io.EOF { + err = io.ErrUnexpectedEOF + } return } @@ -439,15 +447,32 @@ func (d *decoder) Read(p []byte) (n int, err error) { nn = len(d.buf) } - nn, d.err = readEncodedData(d.r, d.buf[d.nbuf:nn], 8-d.nbuf) + // Minimum amount of bytes that needs to be read each cycle + var min int + var expectsPadding bool + if d.enc.padChar == NoPadding { + min = 1 + expectsPadding = false + } else { + min = 8 - d.nbuf + expectsPadding = true + } + + nn, d.err = readEncodedData(d.r, d.buf[d.nbuf:nn], min, expectsPadding) d.nbuf += nn - if d.nbuf < 8 { + if d.nbuf < min { return 0, d.err } // Decode chunk into p, or d.out and then p if p is too small. - nr := d.nbuf / 8 * 8 - nw := d.nbuf / 8 * 5 + var nr int + if d.enc.padChar == NoPadding { + nr = d.nbuf + } else { + nr = d.nbuf / 8 * 8 + } + nw := d.enc.DecodedLen(d.nbuf) + if nw > len(p) { nw, d.end, err = d.enc.decode(d.outbuf[0:], d.buf[0:nr]) d.out = d.outbuf[0:nw] diff --git a/libgo/go/encoding/base32/base32_test.go b/libgo/go/encoding/base32/base32_test.go index 56b229d15a6..c5506ed4de7 100644 --- a/libgo/go/encoding/base32/base32_test.go +++ b/libgo/go/encoding/base32/base32_test.go @@ -530,6 +530,86 @@ func TestDecodeWithWrongPadding(t *testing.T) { } } +func TestBufferedDecodingSameError(t *testing.T) { + testcases := []struct { + prefix string + chunkCombinations [][]string + expected error + }{ + // NBSWY3DPO5XXE3DE == helloworld + // Test with "ZZ" as extra input + {"helloworld", [][]string{ + []string{"NBSW", "Y3DP", "O5XX", "E3DE", "ZZ"}, + []string{"NBSWY3DPO5XXE3DE", "ZZ"}, + []string{"NBSWY3DPO5XXE3DEZZ"}, + []string{"NBS", "WY3", "DPO", "5XX", "E3D", "EZZ"}, + []string{"NBSWY3DPO5XXE3", "DEZZ"}, + }, io.ErrUnexpectedEOF}, + + // Test with "ZZY" as extra input + {"helloworld", [][]string{ + []string{"NBSW", "Y3DP", "O5XX", "E3DE", "ZZY"}, + []string{"NBSWY3DPO5XXE3DE", "ZZY"}, + []string{"NBSWY3DPO5XXE3DEZZY"}, + []string{"NBS", "WY3", "DPO", "5XX", "E3D", "EZZY"}, + []string{"NBSWY3DPO5XXE3", "DEZZY"}, + }, io.ErrUnexpectedEOF}, + + // Normal case, this is valid input + {"helloworld", [][]string{ + []string{"NBSW", "Y3DP", "O5XX", "E3DE"}, + []string{"NBSWY3DPO5XXE3DE"}, + []string{"NBS", "WY3", "DPO", "5XX", "E3D", "E"}, + []string{"NBSWY3DPO5XXE3", "DE"}, + }, nil}, + + // MZXW6YTB = fooba + {"fooba", [][]string{ + []string{"MZXW6YTBZZ"}, + []string{"MZXW6YTBZ", "Z"}, + []string{"MZXW6YTB", "ZZ"}, + []string{"MZXW6YT", "BZZ"}, + []string{"MZXW6Y", "TBZZ"}, + []string{"MZXW6Y", "TB", "ZZ"}, + []string{"MZXW6", "YTBZZ"}, + []string{"MZXW6", "YTB", "ZZ"}, + []string{"MZXW6", "YT", "BZZ"}, + }, io.ErrUnexpectedEOF}, + + // Normal case, this is valid input + {"fooba", [][]string{ + []string{"MZXW6YTB"}, + []string{"MZXW6YT", "B"}, + []string{"MZXW6Y", "TB"}, + []string{"MZXW6", "YTB"}, + []string{"MZXW6", "YT", "B"}, + []string{"MZXW", "6YTB"}, + []string{"MZXW", "6Y", "TB"}, + }, nil}, + } + + for _, testcase := range testcases { + for _, chunks := range testcase.chunkCombinations { + pr, pw := io.Pipe() + + // Write the encoded chunks into the pipe + go func() { + for _, chunk := range chunks { + pw.Write([]byte(chunk)) + } + pw.Close() + }() + + decoder := NewDecoder(StdEncoding, pr) + _, err := ioutil.ReadAll(decoder) + + if err != testcase.expected { + t.Errorf("Expected %v, got %v; case %s %+v", testcase.expected, err, testcase.prefix, chunks) + } + } + } +} + func TestEncodedDecodedLen(t *testing.T) { type test struct { in int @@ -578,3 +658,94 @@ func TestEncodedDecodedLen(t *testing.T) { }) } } + +func TestWithoutPaddingClose(t *testing.T) { + encodings := []*Encoding{ + StdEncoding, + StdEncoding.WithPadding(NoPadding), + } + + for _, encoding := range encodings { + for _, testpair := range pairs { + + var buf bytes.Buffer + encoder := NewEncoder(encoding, &buf) + encoder.Write([]byte(testpair.decoded)) + encoder.Close() + + expected := testpair.encoded + if encoding.padChar == NoPadding { + expected = strings.Replace(expected, "=", "", -1) + } + + res := buf.String() + + if res != expected { + t.Errorf("Expected %s got %s; padChar=%d", expected, res, encoding.padChar) + } + } + } +} + +func TestDecodeReadAll(t *testing.T) { + encodings := []*Encoding{ + StdEncoding, + StdEncoding.WithPadding(NoPadding), + } + + for _, pair := range pairs { + for encIndex, encoding := range encodings { + encoded := pair.encoded + if encoding.padChar == NoPadding { + encoded = strings.Replace(encoded, "=", "", -1) + } + + decReader, err := ioutil.ReadAll(NewDecoder(encoding, strings.NewReader(encoded))) + if err != nil { + t.Errorf("NewDecoder error: %v", err) + } + + if pair.decoded != string(decReader) { + t.Errorf("Expected %s got %s; Encoding %d", pair.decoded, decReader, encIndex) + } + } + } +} + +func TestDecodeSmallBuffer(t *testing.T) { + encodings := []*Encoding{ + StdEncoding, + StdEncoding.WithPadding(NoPadding), + } + + for bufferSize := 1; bufferSize < 200; bufferSize++ { + for _, pair := range pairs { + for encIndex, encoding := range encodings { + encoded := pair.encoded + if encoding.padChar == NoPadding { + encoded = strings.Replace(encoded, "=", "", -1) + } + + decoder := NewDecoder(encoding, strings.NewReader(encoded)) + + var allRead []byte + + for { + buf := make([]byte, bufferSize) + n, err := decoder.Read(buf) + allRead = append(allRead, buf[0:n]...) + if err == io.EOF { + break + } + if err != nil { + t.Error(err) + } + } + + if pair.decoded != string(allRead) { + t.Errorf("Expected %s got %s; Encoding %d; bufferSize %d", pair.decoded, allRead, encIndex, bufferSize) + } + } + } + } +} diff --git a/libgo/go/encoding/base64/base64_test.go b/libgo/go/encoding/base64/base64_test.go index 9f5c493dbfe..f019654f5b5 100644 --- a/libgo/go/encoding/base64/base64_test.go +++ b/libgo/go/encoding/base64/base64_test.go @@ -159,7 +159,7 @@ func TestDecode(t *testing.T) { dbuf, err = tt.enc.DecodeString(encoded) testEqual(t, "DecodeString(%q) = error %v, want %v", encoded, err, error(nil)) - testEqual(t, "DecodeString(%q) = %q, want %q", string(dbuf), p.decoded) + testEqual(t, "DecodeString(%q) = %q, want %q", encoded, string(dbuf), p.decoded) } } } diff --git a/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go index 2d01a3cb287..85b3bc2295d 100644 --- a/libgo/go/encoding/binary/binary.go +++ b/libgo/go/encoding/binary/binary.go @@ -419,70 +419,71 @@ func sizeof(t reflect.Type) int { } type coder struct { - order ByteOrder - buf []byte + order ByteOrder + buf []byte + offset int } type decoder coder type encoder coder func (d *decoder) bool() bool { - x := d.buf[0] - d.buf = d.buf[1:] + x := d.buf[d.offset] + d.offset++ return x != 0 } func (e *encoder) bool(x bool) { if x { - e.buf[0] = 1 + e.buf[e.offset] = 1 } else { - e.buf[0] = 0 + e.buf[e.offset] = 0 } - e.buf = e.buf[1:] + e.offset++ } func (d *decoder) uint8() uint8 { - x := d.buf[0] - d.buf = d.buf[1:] + x := d.buf[d.offset] + d.offset++ return x } func (e *encoder) uint8(x uint8) { - e.buf[0] = x - e.buf = e.buf[1:] + e.buf[e.offset] = x + e.offset++ } func (d *decoder) uint16() uint16 { - x := d.order.Uint16(d.buf[0:2]) - d.buf = d.buf[2:] + x := d.order.Uint16(d.buf[d.offset : d.offset+2]) + d.offset += 2 return x } func (e *encoder) uint16(x uint16) { - e.order.PutUint16(e.buf[0:2], x) - e.buf = e.buf[2:] + e.order.PutUint16(e.buf[e.offset:e.offset+2], x) + e.offset += 2 } func (d *decoder) uint32() uint32 { - x := d.order.Uint32(d.buf[0:4]) - d.buf = d.buf[4:] + x := d.order.Uint32(d.buf[d.offset : d.offset+4]) + d.offset += 4 return x } func (e *encoder) uint32(x uint32) { - e.order.PutUint32(e.buf[0:4], x) - e.buf = e.buf[4:] + e.order.PutUint32(e.buf[e.offset:e.offset+4], x) + e.offset += 4 } func (d *decoder) uint64() uint64 { - x := d.order.Uint64(d.buf[0:8]) - d.buf = d.buf[8:] + x := d.order.Uint64(d.buf[d.offset : d.offset+8]) + d.offset += 8 return x } func (e *encoder) uint64(x uint64) { - e.order.PutUint64(e.buf[0:8], x) - e.buf = e.buf[8:] + e.order.PutUint64(e.buf[e.offset:e.offset+8], x) + e.offset += 8 } func (d *decoder) int8() int8 { return int8(d.uint8()) } @@ -646,15 +647,16 @@ func (e *encoder) value(v reflect.Value) { } func (d *decoder) skip(v reflect.Value) { - d.buf = d.buf[dataSize(v):] + d.offset += dataSize(v) } func (e *encoder) skip(v reflect.Value) { n := dataSize(v) - for i := range e.buf[0:n] { - e.buf[i] = 0 + zero := e.buf[e.offset : e.offset+n] + for i := range zero { + zero[i] = 0 } - e.buf = e.buf[n:] + e.offset += n } // intDataSize returns the size of the data required to represent the data when encoded. @@ -663,6 +665,8 @@ func intDataSize(data interface{}) int { switch data := data.(type) { case bool, int8, uint8, *bool, *int8, *uint8: return 1 + case []bool: + return len(data) case []int8: return len(data) case []uint8: diff --git a/libgo/go/encoding/csv/reader.go b/libgo/go/encoding/csv/reader.go index 2efc7ad0943..a2fd4c0970d 100644 --- a/libgo/go/encoding/csv/reader.go +++ b/libgo/go/encoding/csv/reader.go @@ -91,7 +91,7 @@ var ( var errInvalidDelim = errors.New("csv: invalid field or comment delimiter") func validDelim(r rune) bool { - return r != 0 && r != '\r' && r != '\n' && utf8.ValidRune(r) && r != utf8.RuneError + return r != 0 && r != '"' && r != '\r' && r != '\n' && utf8.ValidRune(r) && r != utf8.RuneError } // A Reader reads records from a CSV-encoded file. diff --git a/libgo/go/encoding/csv/reader_test.go b/libgo/go/encoding/csv/reader_test.go index 1fc69f9ab88..5121791cb36 100644 --- a/libgo/go/encoding/csv/reader_test.go +++ b/libgo/go/encoding/csv/reader_test.go @@ -359,6 +359,10 @@ x,,, Error: errInvalidDelim, }, { Name: "BadComma3", + Comma: '"', + Error: errInvalidDelim, + }, { + Name: "BadComma4", Comma: utf8.RuneError, Error: errInvalidDelim, }, { diff --git a/libgo/go/encoding/csv/writer.go b/libgo/go/encoding/csv/writer.go index ef3594e523c..31c4f9c22dc 100644 --- a/libgo/go/encoding/csv/writer.go +++ b/libgo/go/encoding/csv/writer.go @@ -57,33 +57,46 @@ func (w *Writer) Write(record []string) error { } continue } + if err := w.w.WriteByte('"'); err != nil { return err } - - for _, r1 := range field { - var err error - switch r1 { - case '"': - _, err = w.w.WriteString(`""`) - case '\r': - if !w.UseCRLF { - err = w.w.WriteByte('\r') - } - case '\n': - if w.UseCRLF { - _, err = w.w.WriteString("\r\n") - } else { - err = w.w.WriteByte('\n') - } - default: - _, err = w.w.WriteRune(r1) + for len(field) > 0 { + // Search for special characters. + i := strings.IndexAny(field, "\"\r\n") + if i < 0 { + i = len(field) } - if err != nil { + + // Copy verbatim everything before the special character. + if _, err := w.w.WriteString(field[:i]); err != nil { return err } - } + field = field[i:] + // Encode the special character. + if len(field) > 0 { + var err error + switch field[0] { + case '"': + _, err = w.w.WriteString(`""`) + case '\r': + if !w.UseCRLF { + err = w.w.WriteByte('\r') + } + case '\n': + if w.UseCRLF { + _, err = w.w.WriteString("\r\n") + } else { + err = w.w.WriteByte('\n') + } + } + field = field[1:] + if err != nil { + return err + } + } + } if err := w.w.WriteByte('"'); err != nil { return err } diff --git a/libgo/go/encoding/csv/writer_test.go b/libgo/go/encoding/csv/writer_test.go index 8ddca0abe0c..011f01c172a 100644 --- a/libgo/go/encoding/csv/writer_test.go +++ b/libgo/go/encoding/csv/writer_test.go @@ -13,7 +13,9 @@ import ( var writeTests = []struct { Input [][]string Output string + Error error UseCRLF bool + Comma rune }{ {Input: [][]string{{"abc"}}, Output: "abc\n"}, {Input: [][]string{{"abc"}}, Output: "abc\r\n", UseCRLF: true}, @@ -39,6 +41,11 @@ var writeTests = []struct { {Input: [][]string{{"a", "a", ""}}, Output: "a,a,\n"}, {Input: [][]string{{"a", "a", "a"}}, Output: "a,a,a\n"}, {Input: [][]string{{`\.`}}, Output: "\"\\.\"\n"}, + {Input: [][]string{{"x09\x41\xb4\x1c", "aktau"}}, Output: "x09\x41\xb4\x1c,aktau\n"}, + {Input: [][]string{{",x09\x41\xb4\x1c", "aktau"}}, Output: "\",x09\x41\xb4\x1c\",aktau\n"}, + {Input: [][]string{{"a", "a", ""}}, Output: "a|a|\n", Comma: '|'}, + {Input: [][]string{{",", ",", ""}}, Output: ",|,|\n", Comma: '|'}, + {Input: [][]string{{"foo"}}, Comma: '"', Error: errInvalidDelim}, } func TestWrite(t *testing.T) { @@ -46,9 +53,12 @@ func TestWrite(t *testing.T) { b := &bytes.Buffer{} f := NewWriter(b) f.UseCRLF = tt.UseCRLF + if tt.Comma != 0 { + f.Comma = tt.Comma + } err := f.WriteAll(tt.Input) - if err != nil { - t.Errorf("Unexpected error: %s\n", err) + if err != tt.Error { + t.Errorf("Unexpected error:\ngot %v\nwant %v", err, tt.Error) } out := b.String() if out != tt.Output { diff --git a/libgo/go/encoding/gob/codec_test.go b/libgo/go/encoding/gob/codec_test.go index 8f7b6f3c62e..520afde34d5 100644 --- a/libgo/go/encoding/gob/codec_test.go +++ b/libgo/go/encoding/gob/codec_test.go @@ -1478,6 +1478,10 @@ func TestFuzzOneByte(t *testing.T) { switch i { case 14, 167, 231, 265: // a slice length, corruptions are not handled yet. continue + case 248: + // Large map size, which currently causes an out of memory panic. + // See golang.org/issue/24308 and golang.org/issue/20221. + continue } indices = append(indices, i) } diff --git a/libgo/go/encoding/gob/dec_helpers.go b/libgo/go/encoding/gob/dec_helpers.go index 3aa038da75e..26eb9e4cd1c 100644 --- a/libgo/go/encoding/gob/dec_helpers.go +++ b/libgo/go/encoding/gob/dec_helpers.go @@ -1,4 +1,4 @@ -// Created by decgen --output dec_helpers.go; DO NOT EDIT +// Code generated by go run decgen.go -output dec_helpers.go; DO NOT EDIT. // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/libgo/go/encoding/gob/decgen.go b/libgo/go/encoding/gob/decgen.go index ef73f2dc4a0..bad4fe5d926 100644 --- a/libgo/go/encoding/gob/decgen.go +++ b/libgo/go/encoding/gob/decgen.go @@ -171,7 +171,7 @@ func main() { log.Fatal("usage: decgen [--output filename]") } var b bytes.Buffer - fmt.Fprintf(&b, "// Created by decgen --output %s; DO NOT EDIT\n", *output) + fmt.Fprintf(&b, "// Code generated by go run decgen.go -output %s; DO NOT EDIT.\n", *output) fmt.Fprint(&b, header) printMaps(&b, "Array") fmt.Fprint(&b, "\n") diff --git a/libgo/go/encoding/gob/decode.go b/libgo/go/encoding/gob/decode.go index 2da913fceb3..d2f6c749b1b 100644 --- a/libgo/go/encoding/gob/decode.go +++ b/libgo/go/encoding/gob/decode.go @@ -1070,14 +1070,14 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de } // compileIgnoreSingle compiles the decoder engine for a non-struct top-level value that will be discarded. -func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err error) { - engine = new(decEngine) +func (dec *Decoder) compileIgnoreSingle(remoteId typeId) *decEngine { + engine := new(decEngine) engine.instr = make([]decInstr, 1) // one item op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp)) ovfl := overflow(dec.typeString(remoteId)) engine.instr[0] = decInstr{*op, 0, nil, ovfl} engine.numInstr = 1 - return + return engine } // compileDec compiles the decoder engine for a value. If the value is not a struct, @@ -1168,7 +1168,7 @@ func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, er if wire != nil && wire.StructT != nil { *enginePtr, err = dec.compileDec(wireId, userType(emptyStructType)) } else { - *enginePtr, err = dec.compileIgnoreSingle(wireId) + *enginePtr = dec.compileIgnoreSingle(wireId) } if err != nil { delete(dec.ignorerCache, wireId) diff --git a/libgo/go/encoding/gob/enc_helpers.go b/libgo/go/encoding/gob/enc_helpers.go index 804e539d84d..c3b4ca8972a 100644 --- a/libgo/go/encoding/gob/enc_helpers.go +++ b/libgo/go/encoding/gob/enc_helpers.go @@ -1,4 +1,4 @@ -// Created by encgen --output enc_helpers.go; DO NOT EDIT +// Code generated by go run encgen.go -output enc_helpers.go; DO NOT EDIT. // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/libgo/go/encoding/gob/encgen.go b/libgo/go/encoding/gob/encgen.go index efdd9282921..0c051d2e844 100644 --- a/libgo/go/encoding/gob/encgen.go +++ b/libgo/go/encoding/gob/encgen.go @@ -150,7 +150,7 @@ func main() { log.Fatal("usage: encgen [--output filename]") } var b bytes.Buffer - fmt.Fprintf(&b, "// Created by encgen --output %s; DO NOT EDIT\n", *output) + fmt.Fprintf(&b, "// Code generated by go run encgen.go -output %s; DO NOT EDIT.\n", *output) fmt.Fprint(&b, header) printMaps(&b, "Array") fmt.Fprint(&b, "\n") diff --git a/libgo/go/encoding/gob/encoder_test.go b/libgo/go/encoding/gob/encoder_test.go index a1ca252ccd1..dc9bbcf35d8 100644 --- a/libgo/go/encoding/gob/encoder_test.go +++ b/libgo/go/encoding/gob/encoder_test.go @@ -10,6 +10,7 @@ import ( "fmt" "io/ioutil" "reflect" + "runtime" "strings" "testing" ) @@ -1014,7 +1015,7 @@ type Bug4Secret struct { } // Test that a failed compilation doesn't leave around an executable encoder. -// Issue 3273. +// Issue 3723. func TestMutipleEncodingsOfBadType(t *testing.T) { x := Bug4Public{ Name: "name", @@ -1130,6 +1131,9 @@ func TestBadData(t *testing.T) { // TestHugeWriteFails tests that enormous messages trigger an error. func TestHugeWriteFails(t *testing.T) { + if runtime.GOARCH == "wasm" { + t.Skip("out of memory on wasm") + } if testing.Short() { // Requires allocating a monster, so don't do this from all.bash. t.Skip("skipping huge allocation in short mode") diff --git a/libgo/go/encoding/hex/hex.go b/libgo/go/encoding/hex/hex.go index e4df6cbd4d1..aee5aecb1a7 100644 --- a/libgo/go/encoding/hex/hex.go +++ b/libgo/go/encoding/hex/hex.go @@ -50,8 +50,8 @@ func DecodedLen(x int) int { return x / 2 } // Decode decodes src into DecodedLen(len(src)) bytes, // returning the actual number of bytes written to dst. // -// Decode expects that src contain only hexadecimal -// characters and that src should have an even length. +// Decode expects that src contains only hexadecimal +// characters and that src has even length. // If the input is malformed, Decode returns the number // of bytes decoded before the error. func Decode(dst, src []byte) (int, error) { @@ -101,10 +101,10 @@ func EncodeToString(src []byte) string { // DecodeString returns the bytes represented by the hexadecimal string s. // -// DecodeString expects that src contain only hexadecimal -// characters and that src should have an even length. -// If the input is malformed, DecodeString returns a string -// containing the bytes decoded before the error. +// DecodeString expects that src contains only hexadecimal +// characters and that src has even length. +// If the input is malformed, DecodeString returns +// the bytes decoded before the error. func DecodeString(s string) ([]byte, error) { src := []byte(s) // We can use the source slice itself as the destination @@ -211,6 +211,7 @@ type dumper struct { buf [14]byte used int // number of bytes in the current line n uint // number of bytes, total + closed bool } func toChar(b byte) byte { @@ -221,6 +222,10 @@ func toChar(b byte) byte { } func (h *dumper) Write(data []byte) (n int, err error) { + if h.closed { + return 0, errors.New("encoding/hex: dumper closed") + } + // Output lines look like: // 00000010 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d |./0123456789:;<=| // ^ offset ^ extra space ^ ASCII of line. @@ -277,6 +282,10 @@ func (h *dumper) Write(data []byte) (n int, err error) { func (h *dumper) Close() (err error) { // See the comments in Write() for the details of this format. + if h.closed { + return + } + h.closed = true if h.used == 0 { return } diff --git a/libgo/go/encoding/hex/hex_test.go b/libgo/go/encoding/hex/hex_test.go index b6bab21c480..6ba054ef9a0 100644 --- a/libgo/go/encoding/hex/hex_test.go +++ b/libgo/go/encoding/hex/hex_test.go @@ -188,6 +188,35 @@ func TestDumper(t *testing.T) { } } +func TestDumper_doubleclose(t *testing.T) { + var out bytes.Buffer + dumper := Dumper(&out) + + dumper.Write([]byte(`gopher`)) + dumper.Close() + dumper.Close() + dumper.Write([]byte(`gopher`)) + dumper.Close() + + expected := "00000000 67 6f 70 68 65 72 |gopher|\n" + if out.String() != expected { + t.Fatalf("got:\n%#v\nwant:\n%#v", out.String(), expected) + } +} + +func TestDumper_earlyclose(t *testing.T) { + var out bytes.Buffer + dumper := Dumper(&out) + + dumper.Close() + dumper.Write([]byte(`gopher`)) + + expected := "" + if out.String() != expected { + t.Fatalf("got:\n%#v\nwant:\n%#v", out.String(), expected) + } +} + func TestDump(t *testing.T) { var in [40]byte for i := range in { diff --git a/libgo/go/encoding/json/bench_test.go b/libgo/go/encoding/json/bench_test.go index 42439eb7054..bd322db2e6f 100644 --- a/libgo/go/encoding/json/bench_test.go +++ b/libgo/go/encoding/json/bench_test.go @@ -13,9 +13,14 @@ package json import ( "bytes" "compress/gzip" + "fmt" + "internal/testenv" "io/ioutil" "os" + "reflect" + "runtime" "strings" + "sync" "testing" ) @@ -265,3 +270,66 @@ func BenchmarkUnmapped(b *testing.B) { } }) } + +func BenchmarkTypeFieldsCache(b *testing.B) { + var maxTypes int = 1e6 + if testenv.Builder() != "" { + maxTypes = 1e3 // restrict cache sizes on builders + } + + // Dynamically generate many new types. + types := make([]reflect.Type, maxTypes) + fs := []reflect.StructField{{ + Type: reflect.TypeOf(""), + Index: []int{0}, + }} + for i := range types { + fs[0].Name = fmt.Sprintf("TypeFieldsCache%d", i) + types[i] = reflect.StructOf(fs) + } + + // clearClear clears the cache. Other JSON operations, must not be running. + clearCache := func() { + fieldCache = sync.Map{} + } + + // MissTypes tests the performance of repeated cache misses. + // This measures the time to rebuild a cache of size nt. + for nt := 1; nt <= maxTypes; nt *= 10 { + ts := types[:nt] + b.Run(fmt.Sprintf("MissTypes%d", nt), func(b *testing.B) { + nc := runtime.GOMAXPROCS(0) + for i := 0; i < b.N; i++ { + clearCache() + var wg sync.WaitGroup + for j := 0; j < nc; j++ { + wg.Add(1) + go func(j int) { + for _, t := range ts[(j*len(ts))/nc : ((j+1)*len(ts))/nc] { + cachedTypeFields(t) + } + wg.Done() + }(j) + } + wg.Wait() + } + }) + } + + // HitTypes tests the performance of repeated cache hits. + // This measures the average time of each cache lookup. + for nt := 1; nt <= maxTypes; nt *= 10 { + // Pre-warm a cache of size nt. + clearCache() + for _, t := range types[:nt] { + cachedTypeFields(t) + } + b.Run(fmt.Sprintf("HitTypes%d", nt), func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + cachedTypeFields(types[0]) + } + }) + }) + } +} diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go index 730fb920ebd..0b29249218a 100644 --- a/libgo/go/encoding/json/decode.go +++ b/libgo/go/encoding/json/decode.go @@ -14,7 +14,6 @@ import ( "errors" "fmt" "reflect" - "runtime" "strconv" "unicode" "unicode/utf16" @@ -168,25 +167,20 @@ func (e *InvalidUnmarshalError) Error() string { return "json: Unmarshal(nil " + e.Type.String() + ")" } -func (d *decodeState) unmarshal(v interface{}) (err error) { - defer func() { - if r := recover(); r != nil { - if _, ok := r.(runtime.Error); ok { - panic(r) - } - err = r.(error) - } - }() - +func (d *decodeState) unmarshal(v interface{}) error { rv := reflect.ValueOf(v) if rv.Kind() != reflect.Ptr || rv.IsNil() { return &InvalidUnmarshalError{reflect.TypeOf(v)} } d.scan.reset() + d.scanWhile(scanSkipSpace) // We decode rv not rv.Elem because the Unmarshaler interface // test must be applied at the top level of the value. - d.value(rv) + err := d.value(rv) + if err != nil { + return err + } return d.savedError } @@ -210,7 +204,7 @@ func (n Number) Int64() (int64, error) { func isValidNumber(s string) bool { // This function implements the JSON numbers grammar. // See https://tools.ietf.org/html/rfc7159#section-6 - // and http://json.org/number.gif + // and https://json.org/number.gif if s == "" { return false @@ -269,9 +263,9 @@ func isValidNumber(s string) bool { // decodeState represents the state while decoding a JSON value. type decodeState struct { data []byte - off int // read offset in data + off int // next read offset in data + opcode int // last read result scan scanner - nextscan scanner // for calls to nextValue errorContext struct { // provides context for type errors Struct string Field string @@ -281,6 +275,11 @@ type decodeState struct { disallowUnknownFields bool } +// readIndex returns the position of the last byte read. +func (d *decodeState) readIndex() int { + return d.off - 1 +} + // errPhase is used for errors that should not happen unless // there is a bug in the JSON decoder or something is editing // the data slice while the decoder executes. @@ -295,11 +294,6 @@ func (d *decodeState) init(data []byte) *decodeState { return d } -// error aborts the decoding by panicking with err. -func (d *decodeState) error(err error) { - panic(d.addErrorContext(err)) -} - // saveError saves the first err it is called with, // for reporting at the end of the unmarshal. func (d *decodeState) saveError(err error) { @@ -321,95 +315,91 @@ func (d *decodeState) addErrorContext(err error) error { return err } -// next cuts off and returns the next full JSON value in d.data[d.off:]. -// The next value is known to be an object or array, not a literal. -func (d *decodeState) next() []byte { - c := d.data[d.off] - item, rest, err := nextValue(d.data[d.off:], &d.nextscan) - if err != nil { - d.error(err) +// skip scans to the end of what was started. +func (d *decodeState) skip() { + s, data, i := &d.scan, d.data, d.off + depth := len(s.parseState) + for { + op := s.step(s, data[i]) + i++ + if len(s.parseState) < depth { + d.off = i + d.opcode = op + return + } } - d.off = len(d.data) - len(rest) +} - // Our scanner has seen the opening brace/bracket - // and thinks we're still in the middle of the object. - // invent a closing brace/bracket to get it out. - if c == '{' { - d.scan.step(&d.scan, '}') +// scanNext processes the byte at d.data[d.off]. +func (d *decodeState) scanNext() { + s, data, i := &d.scan, d.data, d.off + if i < len(data) { + d.opcode = s.step(s, data[i]) + d.off = i + 1 } else { - d.scan.step(&d.scan, ']') + d.opcode = s.eof() + d.off = len(data) + 1 // mark processed EOF with len+1 } - - return item } // scanWhile processes bytes in d.data[d.off:] until it // receives a scan code not equal to op. -// It updates d.off and returns the new scan code. -func (d *decodeState) scanWhile(op int) int { - var newOp int - for { - if d.off >= len(d.data) { - newOp = d.scan.eof() - d.off = len(d.data) + 1 // mark processed EOF with len+1 - } else { - c := d.data[d.off] - d.off++ - newOp = d.scan.step(&d.scan, c) - } +func (d *decodeState) scanWhile(op int) { + s, data, i := &d.scan, d.data, d.off + for i < len(d.data) { + newOp := s.step(s, data[i]) + i++ if newOp != op { - break + d.opcode = newOp + d.off = i + return } } - return newOp + + d.off = len(d.data) + 1 // mark processed EOF with len+1 + d.opcode = d.scan.eof() } -// value decodes a JSON value from d.data[d.off:] into the value. -// it updates d.off to point past the decoded value. -func (d *decodeState) value(v reflect.Value) { - if !v.IsValid() { - _, rest, err := nextValue(d.data[d.off:], &d.nextscan) - if err != nil { - d.error(err) - } - d.off = len(d.data) - len(rest) - - // d.scan thinks we're still at the beginning of the item. - // Feed in an empty string - the shortest, simplest value - - // so that it knows we got to the end of the value. - if d.scan.redo { - // rewind. - d.scan.redo = false - d.scan.step = stateBeginValue - } - d.scan.step(&d.scan, '"') - d.scan.step(&d.scan, '"') - - n := len(d.scan.parseState) - if n > 0 && d.scan.parseState[n-1] == parseObjectKey { - // d.scan thinks we just read an object key; finish the object - d.scan.step(&d.scan, ':') - d.scan.step(&d.scan, '"') - d.scan.step(&d.scan, '"') - d.scan.step(&d.scan, '}') - } - - return - } - - switch op := d.scanWhile(scanSkipSpace); op { +// value consumes a JSON value from d.data[d.off-1:], decoding into v, and +// reads the following byte ahead. If v is invalid, the value is discarded. +// The first byte of the value has been read already. +func (d *decodeState) value(v reflect.Value) error { + switch d.opcode { default: - d.error(errPhase) + return errPhase case scanBeginArray: - d.array(v) + if v.IsValid() { + if err := d.array(v); err != nil { + return err + } + } else { + d.skip() + } + d.scanNext() case scanBeginObject: - d.object(v) + if v.IsValid() { + if err := d.object(v); err != nil { + return err + } + } else { + d.skip() + } + d.scanNext() case scanBeginLiteral: - d.literal(v) + // All bytes inside literal return scanContinue op code. + start := d.readIndex() + d.scanWhile(scanContinue) + + if v.IsValid() { + if err := d.literalStore(d.data[start:d.readIndex()], v, false); err != nil { + return err + } + } } + return nil } type unquotedValue struct{} @@ -418,31 +408,37 @@ type unquotedValue struct{} // quoted string literal or literal null into an interface value. // If it finds anything other than a quoted string literal or null, // valueQuoted returns unquotedValue{}. -func (d *decodeState) valueQuoted() interface{} { - switch op := d.scanWhile(scanSkipSpace); op { +func (d *decodeState) valueQuoted() (interface{}, error) { + switch d.opcode { default: - d.error(errPhase) + return nil, errPhase case scanBeginArray: - d.array(reflect.Value{}) + d.skip() + d.scanNext() case scanBeginObject: - d.object(reflect.Value{}) + d.skip() + d.scanNext() case scanBeginLiteral: - switch v := d.literalInterface().(type) { + v, err := d.literalInterface() + if err != nil { + return nil, err + } + switch v.(type) { case nil, string: - return v + return v, nil } } - return unquotedValue{} + return unquotedValue{}, nil } // indirect walks down v allocating pointers as needed, // until it gets to a non-pointer. // if it encounters an Unmarshaler, indirect stops and returns that. // if decodingNull is true, indirect stops at the last pointer so it can be set to nil. -func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { +func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { // Issue #24153 indicates that it is generally not a guaranteed property // that you may round-trip a reflect.Value by calling Value.Addr().Elem() // and expect the value to still be settable for values derived from @@ -507,26 +503,21 @@ func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, return nil, nil, v } -// array consumes an array from d.data[d.off-1:], decoding into the value v. -// the first byte of the array ('[') has been read already. -func (d *decodeState) array(v reflect.Value) { +// array consumes an array from d.data[d.off-1:], decoding into v. +// The first byte of the array ('[') has been read already. +func (d *decodeState) array(v reflect.Value) error { // Check for unmarshaler. - u, ut, pv := d.indirect(v, false) + u, ut, pv := indirect(v, false) if u != nil { - d.off-- - err := u.UnmarshalJSON(d.next()) - if err != nil { - d.error(err) - } - return + start := d.readIndex() + d.skip() + return u.UnmarshalJSON(d.data[start:d.off]) } if ut != nil { d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) - d.off-- - d.next() - return + d.skip() + return nil } - v = pv // Check type of target. @@ -534,16 +525,19 @@ func (d *decodeState) array(v reflect.Value) { case reflect.Interface: if v.NumMethod() == 0 { // Decoding into nil interface? Switch to non-reflect code. - v.Set(reflect.ValueOf(d.arrayInterface())) - return + ai, err := d.arrayInterface() + if err != nil { + return err + } + v.Set(reflect.ValueOf(ai)) + return nil } // Otherwise it's invalid. fallthrough default: d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) - d.off-- - d.next() - return + d.skip() + return nil case reflect.Array: case reflect.Slice: break @@ -552,15 +546,11 @@ func (d *decodeState) array(v reflect.Value) { i := 0 for { // Look ahead for ] - can only happen on first iteration. - op := d.scanWhile(scanSkipSpace) - if op == scanEndArray { + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndArray { break } - // Back up so d.value can have the byte we just read. - d.off-- - d.scan.undo(op) - // Get element of array, growing if necessary. if v.Kind() == reflect.Slice { // Grow slice if necessary @@ -580,20 +570,26 @@ func (d *decodeState) array(v reflect.Value) { if i < v.Len() { // Decode into element. - d.value(v.Index(i)) + if err := d.value(v.Index(i)); err != nil { + return err + } } else { // Ran out of fixed array: skip. - d.value(reflect.Value{}) + if err := d.value(reflect.Value{}); err != nil { + return err + } } i++ // Next token must be , or ]. - op = d.scanWhile(scanSkipSpace) - if op == scanEndArray { + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndArray { break } - if op != scanArrayValue { - d.error(errPhase) + if d.opcode != scanArrayValue { + return errPhase } } @@ -611,36 +607,37 @@ func (d *decodeState) array(v reflect.Value) { if i == 0 && v.Kind() == reflect.Slice { v.Set(reflect.MakeSlice(v.Type(), 0, 0)) } + return nil } var nullLiteral = []byte("null") var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem() -// object consumes an object from d.data[d.off-1:], decoding into the value v. -// the first byte ('{') of the object has been read already. -func (d *decodeState) object(v reflect.Value) { +// object consumes an object from d.data[d.off-1:], decoding into v. +// The first byte ('{') of the object has been read already. +func (d *decodeState) object(v reflect.Value) error { // Check for unmarshaler. - u, ut, pv := d.indirect(v, false) + u, ut, pv := indirect(v, false) if u != nil { - d.off-- - err := u.UnmarshalJSON(d.next()) - if err != nil { - d.error(err) - } - return + start := d.readIndex() + d.skip() + return u.UnmarshalJSON(d.data[start:d.off]) } if ut != nil { d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)}) - d.off-- - d.next() // skip over { } in input - return + d.skip() + return nil } v = pv // Decoding into nil interface? Switch to non-reflect code. if v.Kind() == reflect.Interface && v.NumMethod() == 0 { - v.Set(reflect.ValueOf(d.objectInterface())) - return + oi, err := d.objectInterface() + if err != nil { + return err + } + v.Set(reflect.ValueOf(oi)) + return nil } // Check type of target: @@ -659,9 +656,8 @@ func (d *decodeState) object(v reflect.Value) { default: if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) { d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)}) - d.off-- - d.next() // skip over { } in input - return + d.skip() + return nil } } if v.IsNil() { @@ -671,31 +667,30 @@ func (d *decodeState) object(v reflect.Value) { // ok default: d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)}) - d.off-- - d.next() // skip over { } in input - return + d.skip() + return nil } var mapElem reflect.Value for { // Read opening " of string key or closing }. - op := d.scanWhile(scanSkipSpace) - if op == scanEndObject { + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndObject { // closing } - can only happen on first iteration. break } - if op != scanBeginLiteral { - d.error(errPhase) + if d.opcode != scanBeginLiteral { + return errPhase } // Read key. - start := d.off - 1 - op = d.scanWhile(scanContinue) - item := d.data[start : d.off-1] + start := d.readIndex() + d.scanWhile(scanContinue) + item := d.data[start:d.readIndex()] key, ok := unquoteBytes(item) if !ok { - d.error(errPhase) + return errPhase } // Figure out field corresponding to key. @@ -756,24 +751,35 @@ func (d *decodeState) object(v reflect.Value) { } // Read : before value. - if op == scanSkipSpace { - op = d.scanWhile(scanSkipSpace) + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) } - if op != scanObjectKey { - d.error(errPhase) + if d.opcode != scanObjectKey { + return errPhase } + d.scanWhile(scanSkipSpace) if destring { - switch qv := d.valueQuoted().(type) { + q, err := d.valueQuoted() + if err != nil { + return err + } + switch qv := q.(type) { case nil: - d.literalStore(nullLiteral, subv, false) + if err := d.literalStore(nullLiteral, subv, false); err != nil { + return err + } case string: - d.literalStore([]byte(qv), subv, true) + if err := d.literalStore([]byte(qv), subv, true); err != nil { + return err + } default: d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type())) } } else { - d.value(subv) + if err := d.value(subv); err != nil { + return err + } } // Write value back to map; @@ -786,7 +792,9 @@ func (d *decodeState) object(v reflect.Value) { kv = reflect.ValueOf(key).Convert(kt) case reflect.PtrTo(kt).Implements(textUnmarshalerType): kv = reflect.New(v.Type().Key()) - d.literalStore(item, kv, true) + if err := d.literalStore(item, kv, true); err != nil { + return err + } kv = kv.Elem() default: switch kt.Kind() { @@ -795,7 +803,7 @@ func (d *decodeState) object(v reflect.Value) { n, err := strconv.ParseInt(s, 10, 64) if err != nil || reflect.Zero(kt).OverflowInt(n) { d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) - return + return nil } kv = reflect.ValueOf(n).Convert(kt) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: @@ -803,7 +811,7 @@ func (d *decodeState) object(v reflect.Value) { n, err := strconv.ParseUint(s, 10, 64) if err != nil || reflect.Zero(kt).OverflowUint(n) { d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) - return + return nil } kv = reflect.ValueOf(n).Convert(kt) default: @@ -814,32 +822,20 @@ func (d *decodeState) object(v reflect.Value) { } // Next token must be , or }. - op = d.scanWhile(scanSkipSpace) - if op == scanEndObject { + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndObject { break } - if op != scanObjectValue { - d.error(errPhase) + if d.opcode != scanObjectValue { + return errPhase } d.errorContext.Struct = "" d.errorContext.Field = "" } -} - -// literal consumes a literal from d.data[d.off-1:], decoding into the value v. -// The first byte of the literal has been read already -// (that's how the caller knows it's a literal). -func (d *decodeState) literal(v reflect.Value) { - // All bytes inside literal return scanContinue op code. - start := d.off - 1 - op := d.scanWhile(scanContinue) - - // Scan read one byte too far; back up. - d.off-- - d.scan.undo(op) - - d.literalStore(d.data[start:d.off], v, false) + return nil } // convertNumber converts the number literal s to a float64 or a Number @@ -862,21 +858,17 @@ var numberType = reflect.TypeOf(Number("")) // fromQuoted indicates whether this literal came from unwrapping a // string from the ",string" struct tag option. this is used only to // produce more helpful error messages. -func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) { +func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error { // Check for unmarshaler. if len(item) == 0 { //Empty string given d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - return + return nil } isNull := item[0] == 'n' // null - u, ut, pv := d.indirect(v, isNull) + u, ut, pv := indirect(v, isNull) if u != nil { - err := u.UnmarshalJSON(item) - if err != nil { - d.error(err) - } - return + return u.UnmarshalJSON(item) } if ut != nil { if item[0] != '"' { @@ -892,23 +884,18 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool default: val = "number" } - d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.off)}) + d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())}) } - return + return nil } s, ok := unquoteBytes(item) if !ok { if fromQuoted { - d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - } else { - d.error(errPhase) + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) } + return errPhase } - err := ut.UnmarshalText(s) - if err != nil { - d.error(err) - } - return + return ut.UnmarshalText(s) } v = pv @@ -939,7 +926,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool if fromQuoted { d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) } else { - d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.off)}) + d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) } case reflect.Bool: v.SetBool(value) @@ -947,7 +934,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool if v.NumMethod() == 0 { v.Set(reflect.ValueOf(value)) } else { - d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.off)}) + d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) } } @@ -955,17 +942,16 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool s, ok := unquoteBytes(item) if !ok { if fromQuoted { - d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - } else { - d.error(errPhase) + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) } + return errPhase } switch v.Kind() { default: - d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)}) + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) case reflect.Slice: if v.Type().Elem().Kind() != reflect.Uint8 { - d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)}) + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) break } b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) @@ -981,17 +967,16 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool if v.NumMethod() == 0 { v.Set(reflect.ValueOf(string(s))) } else { - d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.off)}) + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) } } default: // number if c != '-' && (c < '0' || c > '9') { if fromQuoted { - d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - } else { - d.error(errPhase) + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) } + return errPhase } s := string(item) switch v.Kind() { @@ -999,15 +984,14 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool if v.Kind() == reflect.String && v.Type() == numberType { v.SetString(s) if !isValidNumber(s) { - d.error(fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item)) + return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item) } break } if fromQuoted { - d.error(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) - } else { - d.error(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.off)}) + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) } + return &UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())} case reflect.Interface: n, err := d.convertNumber(s) if err != nil { @@ -1015,7 +999,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool break } if v.NumMethod() != 0 { - d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.off)}) + d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}) break } v.Set(reflect.ValueOf(n)) @@ -1023,7 +1007,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: n, err := strconv.ParseInt(s, 10, 64) if err != nil || v.OverflowInt(n) { - d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)}) + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) break } v.SetInt(n) @@ -1031,7 +1015,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: n, err := strconv.ParseUint(s, 10, 64) if err != nil || v.OverflowUint(n) { - d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)}) + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) break } v.SetUint(n) @@ -1039,12 +1023,13 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool case reflect.Float32, reflect.Float64: n, err := strconv.ParseFloat(s, v.Type().Bits()) if err != nil || v.OverflowFloat(n) { - d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.off)}) + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) break } v.SetFloat(n) } } + return nil } // The xxxInterface routines build up a value to be stored @@ -1052,128 +1037,138 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool // but they avoid the weight of reflection in this common case. // valueInterface is like value but returns interface{} -func (d *decodeState) valueInterface() interface{} { - switch d.scanWhile(scanSkipSpace) { +func (d *decodeState) valueInterface() (val interface{}, err error) { + switch d.opcode { default: - d.error(errPhase) - panic("unreachable") + err = errPhase case scanBeginArray: - return d.arrayInterface() + val, err = d.arrayInterface() + d.scanNext() case scanBeginObject: - return d.objectInterface() + val, err = d.objectInterface() + d.scanNext() case scanBeginLiteral: - return d.literalInterface() + val, err = d.literalInterface() } + return } // arrayInterface is like array but returns []interface{}. -func (d *decodeState) arrayInterface() []interface{} { +func (d *decodeState) arrayInterface() ([]interface{}, error) { var v = make([]interface{}, 0) for { // Look ahead for ] - can only happen on first iteration. - op := d.scanWhile(scanSkipSpace) - if op == scanEndArray { + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndArray { break } - // Back up so d.value can have the byte we just read. - d.off-- - d.scan.undo(op) - - v = append(v, d.valueInterface()) + vi, err := d.valueInterface() + if err != nil { + return nil, err + } + v = append(v, vi) // Next token must be , or ]. - op = d.scanWhile(scanSkipSpace) - if op == scanEndArray { + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndArray { break } - if op != scanArrayValue { - d.error(errPhase) + if d.opcode != scanArrayValue { + return nil, errPhase } } - return v + return v, nil } // objectInterface is like object but returns map[string]interface{}. -func (d *decodeState) objectInterface() map[string]interface{} { +func (d *decodeState) objectInterface() (map[string]interface{}, error) { m := make(map[string]interface{}) for { // Read opening " of string key or closing }. - op := d.scanWhile(scanSkipSpace) - if op == scanEndObject { + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndObject { // closing } - can only happen on first iteration. break } - if op != scanBeginLiteral { - d.error(errPhase) + if d.opcode != scanBeginLiteral { + return nil, errPhase } // Read string key. - start := d.off - 1 - op = d.scanWhile(scanContinue) - item := d.data[start : d.off-1] + start := d.readIndex() + d.scanWhile(scanContinue) + item := d.data[start:d.readIndex()] key, ok := unquote(item) if !ok { - d.error(errPhase) + return nil, errPhase } // Read : before value. - if op == scanSkipSpace { - op = d.scanWhile(scanSkipSpace) + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) } - if op != scanObjectKey { - d.error(errPhase) + if d.opcode != scanObjectKey { + return nil, errPhase } + d.scanWhile(scanSkipSpace) // Read value. - m[key] = d.valueInterface() + vi, err := d.valueInterface() + if err != nil { + return nil, err + } + m[key] = vi // Next token must be , or }. - op = d.scanWhile(scanSkipSpace) - if op == scanEndObject { + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndObject { break } - if op != scanObjectValue { - d.error(errPhase) + if d.opcode != scanObjectValue { + return nil, errPhase } } - return m + return m, nil } -// literalInterface is like literal but returns an interface value. -func (d *decodeState) literalInterface() interface{} { +// literalInterface consumes and returns a literal from d.data[d.off-1:] and +// it reads the following byte ahead. The first byte of the literal has been +// read already (that's how the caller knows it's a literal). +func (d *decodeState) literalInterface() (interface{}, error) { // All bytes inside literal return scanContinue op code. - start := d.off - 1 - op := d.scanWhile(scanContinue) + start := d.readIndex() + d.scanWhile(scanContinue) - // Scan read one byte too far; back up. - d.off-- - d.scan.undo(op) - item := d.data[start:d.off] + item := d.data[start:d.readIndex()] switch c := item[0]; c { case 'n': // null - return nil + return nil, nil case 't', 'f': // true, false - return c == 't' + return c == 't', nil case '"': // string s, ok := unquote(item) if !ok { - d.error(errPhase) + return nil, errPhase } - return s + return s, nil default: // number if c != '-' && (c < '0' || c > '9') { - d.error(errPhase) + return nil, errPhase } n, err := d.convertNumber(string(item)) if err != nil { d.saveError(err) } - return n + return n, nil } } diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go index fa1531f3761..ab83b81bb39 100644 --- a/libgo/go/encoding/json/decode_test.go +++ b/libgo/go/encoding/json/decode_test.go @@ -2208,3 +2208,17 @@ func TestUnmarshalEmbeddedUnexported(t *testing.T) { } } } + +type unmarshalPanic struct{} + +func (unmarshalPanic) UnmarshalJSON([]byte) error { panic(0xdead) } + +func TestUnmarshalPanic(t *testing.T) { + defer func() { + if got := recover(); !reflect.DeepEqual(got, 0xdead) { + t.Errorf("panic() = (%T)(%v), want 0xdead", got, got) + } + }() + Unmarshal([]byte("{}"), &unmarshalPanic{}) + t.Fatalf("Unmarshal should have panicked") +} diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go index 1e45e445d92..28ca5fe9e00 100644 --- a/libgo/go/encoding/json/encode.go +++ b/libgo/go/encoding/json/encode.go @@ -17,12 +17,10 @@ import ( "fmt" "math" "reflect" - "runtime" "sort" "strconv" "strings" "sync" - "sync/atomic" "unicode" "unicode/utf8" ) @@ -157,12 +155,18 @@ import ( // an infinite recursion. // func Marshal(v interface{}) ([]byte, error) { - e := &encodeState{} + e := newEncodeState() + err := e.marshal(v, encOpts{escapeHTML: true}) if err != nil { return nil, err } - return e.Bytes(), nil + buf := append([]byte(nil), e.Bytes()...) + + e.Reset() + encodeStatePool.Put(e) + + return buf, nil } // MarshalIndent is like Marshal but applies Indent to format the output. @@ -283,24 +287,28 @@ func newEncodeState() *encodeState { return new(encodeState) } +// jsonError is an error wrapper type for internal use only. +// Panics with errors are wrapped in jsonError so that the top-level recover +// can distinguish intentional panics from this package. +type jsonError struct{ error } + func (e *encodeState) marshal(v interface{}, opts encOpts) (err error) { defer func() { if r := recover(); r != nil { - if _, ok := r.(runtime.Error); ok { + if je, ok := r.(jsonError); ok { + err = je.error + } else { panic(r) } - if s, ok := r.(string); ok { - panic(s) - } - err = r.(error) } }() e.reflectValue(reflect.ValueOf(v), opts) return nil } +// error aborts the encoding by panicking with err wrapped in jsonError. func (e *encodeState) error(err error) { - panic(err) + panic(jsonError{err}) } func isEmptyValue(v reflect.Value) bool { @@ -1229,65 +1237,22 @@ func typeFields(t reflect.Type) []field { // will be false: This condition is an error in Go and we skip all // the fields. func dominantField(fields []field) (field, bool) { - // The fields are sorted in increasing index-length order. The winner - // must therefore be one with the shortest index length. Drop all - // longer entries, which is easy: just truncate the slice. - length := len(fields[0].index) - tagged := -1 // Index of first tagged field. - for i, f := range fields { - if len(f.index) > length { - fields = fields[:i] - break - } - if f.tag { - if tagged >= 0 { - // Multiple tagged fields at the same level: conflict. - // Return no field. - return field{}, false - } - tagged = i - } - } - if tagged >= 0 { - return fields[tagged], true - } - // All remaining fields have the same length. If there's more than one, - // we have a conflict (two fields named "X" at the same level) and we - // return no field. - if len(fields) > 1 { + // The fields are sorted in increasing index-length order, then by presence of tag. + // That means that the first field is the dominant one. We need only check + // for error cases: two fields at top level, either both tagged or neither tagged. + if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag { return field{}, false } return fields[0], true } -var fieldCache struct { - value atomic.Value // map[reflect.Type][]field - mu sync.Mutex // used only by writers -} +var fieldCache sync.Map // map[reflect.Type][]field // cachedTypeFields is like typeFields but uses a cache to avoid repeated work. func cachedTypeFields(t reflect.Type) []field { - m, _ := fieldCache.value.Load().(map[reflect.Type][]field) - f := m[t] - if f != nil { - return f + if f, ok := fieldCache.Load(t); ok { + return f.([]field) } - - // Compute fields without lock. - // Might duplicate effort but won't hold other computations back. - f = typeFields(t) - if f == nil { - f = []field{} - } - - fieldCache.mu.Lock() - m, _ = fieldCache.value.Load().(map[reflect.Type][]field) - newM := make(map[reflect.Type][]field, len(m)+1) - for k, v := range m { - newM[k] = v - } - newM[t] = f - fieldCache.value.Store(newM) - fieldCache.mu.Unlock() - return f + f, _ := fieldCache.LoadOrStore(t, typeFields(t)) + return f.([]field) } diff --git a/libgo/go/encoding/json/encode_test.go b/libgo/go/encoding/json/encode_test.go index 0f194e13d26..b90483cf35f 100644 --- a/libgo/go/encoding/json/encode_test.go +++ b/libgo/go/encoding/json/encode_test.go @@ -981,3 +981,17 @@ func TestMarshalRawMessageValue(t *testing.T) { } } } + +type marshalPanic struct{} + +func (marshalPanic) MarshalJSON() ([]byte, error) { panic(0xdead) } + +func TestMarshalPanic(t *testing.T) { + defer func() { + if got := recover(); !reflect.DeepEqual(got, 0xdead) { + t.Errorf("panic() = (%T)(%v), want 0xdead", got, got) + } + }() + Marshal(&marshalPanic{}) + t.Error("Marshal should have panicked") +} diff --git a/libgo/go/encoding/json/number_test.go b/libgo/go/encoding/json/number_test.go index 4b869996388..cc6701814fb 100644 --- a/libgo/go/encoding/json/number_test.go +++ b/libgo/go/encoding/json/number_test.go @@ -10,7 +10,7 @@ import ( ) func TestNumberIsValid(t *testing.T) { - // From: http://stackoverflow.com/a/13340826 + // From: https://stackoverflow.com/a/13340826 var jsonNumberRegexp = regexp.MustCompile(`^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$`) validTests := []string{ diff --git a/libgo/go/encoding/json/scanner.go b/libgo/go/encoding/json/scanner.go index ae34418d1da..9e6d482e168 100644 --- a/libgo/go/encoding/json/scanner.go +++ b/libgo/go/encoding/json/scanner.go @@ -8,7 +8,7 @@ package json // Just about at the limit of what is reasonable to write by hand. // Some parts are a bit tedious, but overall it nicely factors out the // otherwise common code from the multiple scanning functions -// in this package (Compact, Indent, checkValid, nextValue, etc). +// in this package (Compact, Indent, checkValid, etc). // // This file starts with two simple examples using the scanner // before diving into the scanner itself. @@ -36,35 +36,6 @@ func checkValid(data []byte, scan *scanner) error { return nil } -// nextValue splits data after the next whole JSON value, -// returning that value and the bytes that follow it as separate slices. -// scan is passed in for use by nextValue to avoid an allocation. -func nextValue(data []byte, scan *scanner) (value, rest []byte, err error) { - scan.reset() - for i, c := range data { - v := scan.step(scan, c) - if v >= scanEndObject { - switch v { - // probe the scanner with a space to determine whether we will - // get scanEnd on the next character. Otherwise, if the next character - // is not a space, scanEndTop allocates a needless error. - case scanEndObject, scanEndArray: - if scan.step(scan, ' ') == scanEnd { - return data[:i+1], data[i+1:], nil - } - case scanError: - return nil, nil, scan.err - case scanEnd: - return data[:i], data[i:], nil - } - } - } - if scan.eof() == scanError { - return nil, nil, scan.err - } - return data, nil, nil -} - // A SyntaxError is a description of a JSON syntax error. type SyntaxError struct { msg string // description of error @@ -101,11 +72,6 @@ type scanner struct { // Error that happened, if any. err error - // 1-byte redo (see undo method) - redo bool - redoCode int - redoState func(*scanner, byte) int - // total bytes consumed, updated by decoder.Decode bytes int64 } @@ -151,7 +117,6 @@ func (s *scanner) reset() { s.step = stateBeginValue s.parseState = s.parseState[0:0] s.err = nil - s.redo = false s.endTop = false } @@ -184,7 +149,6 @@ func (s *scanner) pushParseState(p int) { func (s *scanner) popParseState() { n := len(s.parseState) - 1 s.parseState = s.parseState[0:n] - s.redo = false if n == 0 { s.step = stateEndTop s.endTop = true @@ -607,22 +571,3 @@ func quoteChar(c byte) string { s := strconv.Quote(string(c)) return "'" + s[1:len(s)-1] + "'" } - -// undo causes the scanner to return scanCode from the next state transition. -// This gives callers a simple 1-byte undo mechanism. -func (s *scanner) undo(scanCode int) { - if s.redo { - panic("json: invalid use of scanner") - } - s.redoCode = scanCode - s.redoState = s.step - s.step = stateRedo - s.redo = true -} - -// stateRedo helps implement the scanner's 1-byte undo. -func stateRedo(s *scanner, c byte) int { - s.redo = false - s.step = s.redoState - return s.redoCode -} diff --git a/libgo/go/encoding/json/scanner_test.go b/libgo/go/encoding/json/scanner_test.go index 0d4518a632b..6cdbe7d301e 100644 --- a/libgo/go/encoding/json/scanner_test.go +++ b/libgo/go/encoding/json/scanner_test.go @@ -200,43 +200,6 @@ func TestIndentErrors(t *testing.T) { } } -func TestNextValueBig(t *testing.T) { - initBig() - var scan scanner - item, rest, err := nextValue(jsonBig, &scan) - if err != nil { - t.Fatalf("nextValue: %s", err) - } - if len(item) != len(jsonBig) || &item[0] != &jsonBig[0] { - t.Errorf("invalid item: %d %d", len(item), len(jsonBig)) - } - if len(rest) != 0 { - t.Errorf("invalid rest: %d", len(rest)) - } - - item, rest, err = nextValue(append(jsonBig, "HELLO WORLD"...), &scan) - if err != nil { - t.Fatalf("nextValue extra: %s", err) - } - if len(item) != len(jsonBig) { - t.Errorf("invalid item: %d %d", len(item), len(jsonBig)) - } - if string(rest) != "HELLO WORLD" { - t.Errorf("invalid rest: %d", len(rest)) - } -} - -var benchScan scanner - -func BenchmarkSkipValue(b *testing.B) { - initBig() - b.ResetTimer() - for i := 0; i < b.N; i++ { - nextValue(jsonBig, &benchScan) - } - b.SetBytes(int64(len(jsonBig))) -} - func diff(t *testing.T, a, b []byte) { for i := 0; ; i++ { if i >= len(a) || i >= len(b) || a[i] != b[i] { diff --git a/libgo/go/encoding/xml/xml.go b/libgo/go/encoding/xml/xml.go index f408623de5e..ca059440a1b 100644 --- a/libgo/go/encoding/xml/xml.go +++ b/libgo/go/encoding/xml/xml.go @@ -7,8 +7,8 @@ package xml // References: -// Annotated XML spec: http://www.xml.com/axml/testaxml.htm -// XML name spaces: http://www.w3.org/TR/REC-xml-names/ +// Annotated XML spec: https://www.xml.com/axml/testaxml.htm +// XML name spaces: https://www.w3.org/TR/REC-xml-names/ // TODO(rsc): // Test error handling. @@ -167,9 +167,9 @@ type Decoder struct { // // Setting: // - // d.Strict = false; - // d.AutoClose = HTMLAutoClose; - // d.Entity = HTMLEntity + // d.Strict = false + // d.AutoClose = xml.HTMLAutoClose + // d.Entity = xml.HTMLEntity // // creates a parser that can handle typical HTML. // @@ -198,7 +198,7 @@ type Decoder struct { // charset-conversion readers, converting from the provided // non-UTF-8 charset into UTF-8. If CharsetReader is nil or // returns an error, parsing stops with an error. One of the - // the CharsetReader's result values must be non-nil. + // CharsetReader's result values must be non-nil. CharsetReader func(charset string, input io.Reader) (io.Reader, error) // DefaultSpace sets the default name space used for unadorned tags, @@ -271,7 +271,7 @@ func NewTokenDecoder(t TokenReader) *Decoder { // it will return an error. // // Token implements XML name spaces as described by -// http://www.w3.org/TR/REC-xml-names/. Each of the +// https://www.w3.org/TR/REC-xml-names/. Each of the // Name structures contained in the Token has the Space // set to the URL identifying its name space when known. // If Token encounters an unrecognized name space prefix, @@ -806,18 +806,7 @@ func (d *Decoder) rawToken() (Token, error) { } d.ungetc(b) - n := len(attr) - if n >= cap(attr) { - nCap := 2 * cap(attr) - if nCap == 0 { - nCap = 4 - } - nattr := make([]Attr, n, nCap) - copy(nattr, attr) - attr = nattr - } - attr = attr[0 : n+1] - a := &attr[n] + a := Attr{} if a.Name, ok = d.nsname(); !ok { if d.err == nil { d.err = d.syntaxError("expected attribute name in element") @@ -843,6 +832,7 @@ func (d *Decoder) rawToken() (Token, error) { } a.Value = string(data) } + attr = append(attr, a) } if empty { d.needClose = true @@ -873,7 +863,7 @@ func (d *Decoder) attrval() []byte { if !ok { return nil } - // http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2 + // https://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2 if 'a' <= b && b <= 'z' || 'A' <= b && b <= 'Z' || '0' <= b && b <= '9' || b == '_' || b == ':' || b == '-' { d.buf.WriteByte(b) @@ -1144,13 +1134,13 @@ Input: } // Decide whether the given rune is in the XML Character Range, per -// the Char production of http://www.xml.com/axml/testaxml.htm, +// the Char production of https://www.xml.com/axml/testaxml.htm, // Section 2.2 Characters. func isInCharacterRange(r rune) (inrange bool) { return r == 0x09 || r == 0x0A || r == 0x0D || - r >= 0x20 && r <= 0xDF77 || + r >= 0x20 && r <= 0xD7FF || r >= 0xE000 && r <= 0xFFFD || r >= 0x10000 && r <= 0x10FFFF } @@ -1273,7 +1263,7 @@ func isNameString(s string) bool { } // These tables were generated by cut and paste from Appendix B of -// the XML spec at http://www.xml.com/axml/testaxml.htm +// the XML spec at https://www.xml.com/axml/testaxml.htm // and then reformatting. First corresponds to (Letter | '_' | ':') // and second corresponds to NameChar. @@ -1591,7 +1581,9 @@ var second = &unicode.RangeTable{ // HTMLEntity is an entity map containing translations for the // standard HTML entity characters. -var HTMLEntity = htmlEntity +// +// See the Decoder.Strict and Decoder.Entity fields' documentation. +var HTMLEntity map[string]string = htmlEntity var htmlEntity = map[string]string{ /* @@ -1858,7 +1850,9 @@ var htmlEntity = map[string]string{ // HTMLAutoClose is the set of HTML elements that // should be considered to close automatically. -var HTMLAutoClose = htmlAutoClose +// +// See the Decoder.Strict and Decoder.Entity fields' documentation. +var HTMLAutoClose []string = htmlAutoClose var htmlAutoClose = []string{ /* @@ -1942,10 +1936,8 @@ func escapeText(w io.Writer, s []byte, escapeNewline bool) error { } last = i } - if _, err := w.Write(s[last:]); err != nil { - return err - } - return nil + _, err := w.Write(s[last:]) + return err } // EscapeString writes to p the properly escaped XML equivalent @@ -2028,10 +2020,8 @@ func emitCDATA(w io.Writer, s []byte) error { } s = s[i:] } - if _, err := w.Write(cdataEnd); err != nil { - return err - } - return nil + _, err := w.Write(cdataEnd) + return err } // procInst parses the `param="..."` or `param='...'` diff --git a/libgo/go/encoding/xml/xml_test.go b/libgo/go/encoding/xml/xml_test.go index 7a3511d5832..ee4ffa24208 100644 --- a/libgo/go/encoding/xml/xml_test.go +++ b/libgo/go/encoding/xml/xml_test.go @@ -650,6 +650,20 @@ func TestDisallowedCharacters(t *testing.T) { } } +func TestIsInCharacterRange(t *testing.T) { + invalid := []rune{ + utf8.MaxRune + 1, + 0xD800, // surrogate min + 0xDFFF, // surrogate max + -1, + } + for _, r := range invalid { + if isInCharacterRange(r) { + t.Errorf("rune %U considered valid", r) + } + } +} + var procInstTests = []struct { input string expect [2]string diff --git a/libgo/go/expvar/expvar.go b/libgo/go/expvar/expvar.go index 8290e0bd72b..174873a7d47 100644 --- a/libgo/go/expvar/expvar.go +++ b/libgo/go/expvar/expvar.go @@ -22,7 +22,6 @@ package expvar import ( - "bytes" "encoding/json" "fmt" "log" @@ -32,6 +31,7 @@ import ( "runtime" "sort" "strconv" + "strings" "sync" "sync/atomic" ) @@ -111,7 +111,7 @@ type KeyValue struct { } func (v *Map) String() string { - var b bytes.Buffer + var b strings.Builder fmt.Fprintf(&b, "{") first := true v.Do(func(kv KeyValue) { diff --git a/libgo/go/flag/example_value_test.go b/libgo/go/flag/example_value_test.go new file mode 100644 index 00000000000..9d464c62e87 --- /dev/null +++ b/libgo/go/flag/example_value_test.go @@ -0,0 +1,44 @@ +// 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 flag_test + +import ( + "flag" + "fmt" + "net/url" +) + +type URLValue struct { + URL *url.URL +} + +func (v URLValue) String() string { + if v.URL != nil { + return v.URL.String() + } + return "" +} + +func (v URLValue) Set(s string) error { + if u, err := url.Parse(s); err != nil { + return err + } else { + *v.URL = *u + } + return nil +} + +var u = &url.URL{} + +func ExampleValue() { + fs := flag.NewFlagSet("ExampleValue", flag.ExitOnError) + fs.Var(&URLValue{u}, "url", "URL to parse") + + fs.Parse([]string{"-url", "https://golang.org/pkg/flag/"}) + fmt.Printf(`{scheme: %q, host: %q, path: %q}`, u.Scheme, u.Host, u.Path) + + // Output: + // {scheme: "https", host: "golang.org", path: "/pkg/flag/"} +} diff --git a/libgo/go/flag/flag.go b/libgo/go/flag/flag.go index edde5282cf4..2cd7829c1a6 100644 --- a/libgo/go/flag/flag.go +++ b/libgo/go/flag/flag.go @@ -5,7 +5,7 @@ /* Package flag implements command-line flag parsing. - Usage: + Usage Define flags using flag.String(), Bool(), Int(), etc. @@ -35,7 +35,10 @@ slice flag.Args() or individually as flag.Arg(i). The arguments are indexed from 0 through flag.NArg()-1. - Command line flag syntax: + Command line flag syntax + + The following forms are permitted: + -flag -flag=x -flag x // non-boolean flags only @@ -395,8 +398,8 @@ func Set(name, value string) error { return CommandLine.Set(name, value) } -// isZeroValue guesses whether the string represents the zero -// value for a flag. It is not accurate but in practice works OK. +// isZeroValue determines whether the string represents the zero +// value for a flag. func isZeroValue(flag *Flag, value string) bool { // Build a zero value of the flag's Value type, and see if the // result of calling its String method equals the value passed in. @@ -408,15 +411,7 @@ func isZeroValue(flag *Flag, value string) bool { } else { z = reflect.Zero(typ) } - if value == z.Interface().(Value).String() { - return true - } - - switch value { - case "false", "", "0": - return true - } - return false + return value == z.Interface().(Value).String() } // UnquoteUsage extracts a back-quoted name from the usage @@ -981,7 +976,8 @@ func commandLineUsage() { } // NewFlagSet returns a new, empty flag set with the specified name and -// error handling property. +// error handling property. If the name is not empty, it will be printed +// in the default usage message and in error messages. func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { f := &FlagSet{ name: name, diff --git a/libgo/go/flag/flag_test.go b/libgo/go/flag/flag_test.go index 67c409f29ba..c7f0c07d448 100644 --- a/libgo/go/flag/flag_test.go +++ b/libgo/go/flag/flag_test.go @@ -386,6 +386,8 @@ const defaultOutput = ` -A for bootstrapping, allow 'any' type -C a boolean defaulting to true (default true) -D path set relative path for local imports + -E string + issue 23543 (default "0") -F number a non-zero number (default 2.7) -G float @@ -412,6 +414,7 @@ func TestPrintDefaults(t *testing.T) { fs.Bool("Alongflagname", false, "disable bounds checking") fs.Bool("C", true, "a boolean defaulting to true") fs.String("D", "", "set relative `path` for local imports") + fs.String("E", "0", "issue 23543") fs.Float64("F", 2.7, "a non-zero `number`") fs.Float64("G", 0, "a float that defaults to zero") fs.String("M", "", "a multiline\nhelp\nstring") diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go index 375cdb4266d..3b657f3681d 100644 --- a/libgo/go/fmt/doc.go +++ b/libgo/go/fmt/doc.go @@ -45,6 +45,8 @@ %q a double-quoted string safely escaped with Go syntax %x base 16, lower-case, two characters per byte %X base 16, upper-case, two characters per byte + Slice: + %p address of 0th element in base 16 notation, with leading 0x Pointer: %p base 16 notation, with leading 0x The %b, %d, %o, %x and %X verbs also work with pointers, @@ -62,7 +64,7 @@ laid out like this: struct: {field0 field1 ...} array, slice: [elem0 elem1 ...] - maps: map[key1:value1 key2:value2] + maps: map[key1:value1 key2:value2 ...] pointer to above: &{}, &[], &map[] Width is specified by an optional decimal number immediately preceding the verb. @@ -95,10 +97,11 @@ For floating-point values, width sets the minimum width of the field and precision sets the number of places after the decimal, if appropriate, - except that for %g/%G precision sets the total number of significant - digits. For example, given 12.345 the format %6.3f prints 12.345 while - %.3g prints 12.3. The default precision for %e, %f and %#g is 6; for %g it - is the smallest number of digits necessary to identify the value uniquely. + except that for %g/%G precision sets the maximum number of significant + digits (trailing zeros are removed). For example, given 12.345 the format + %6.3f prints 12.345 while %.3g prints 12.3. The default precision for %e, %f + and %#g is 6; for %g it is the smallest number of digits necessary to identify + the value uniquely. For complex numbers, the width and precision apply to the two components independently and the result is parenthesized, so %f applied @@ -279,9 +282,11 @@ The verbs behave analogously to those of Printf. For example, %x will scan an integer as a hexadecimal number, and %v will scan the default representation format for the value. - The Printf verbs %p and %T and the flags # and + are not implemented, - and the verbs %e %E %f %F %g and %G are all equivalent and scan any - floating-point or complex value. + The Printf verbs %p and %T and the flags # and + are not implemented. + The verbs %e %E %f %F %g and %G are all equivalent and scan any + floating-point or complex value. For float and complex literals in + scientific notation, both the decimal (e) and binary (p) exponent + formats are supported (for example: "2.3e+7" and "4.5p-8"). Input processed by verbs is implicitly space-delimited: the implementation of every verb except %c starts by discarding diff --git a/libgo/go/fmt/format.go b/libgo/go/fmt/format.go index d4b92f81214..91103f2c07f 100644 --- a/libgo/go/fmt/format.go +++ b/libgo/go/fmt/format.go @@ -122,8 +122,8 @@ func (f *fmt) padString(s string) { } } -// fmt_boolean formats a boolean. -func (f *fmt) fmt_boolean(v bool) { +// fmtBoolean formats a boolean. +func (f *fmt) fmtBoolean(v bool) { if v { f.padString("true") } else { @@ -131,8 +131,8 @@ func (f *fmt) fmt_boolean(v bool) { } } -// fmt_unicode formats a uint64 as "U+0078" or with f.sharp set as "U+0078 'x'". -func (f *fmt) fmt_unicode(u uint64) { +// fmtUnicode formats a uint64 as "U+0078" or with f.sharp set as "U+0078 'x'". +func (f *fmt) fmtUnicode(u uint64) { buf := f.intbuf[0:] // With default precision set the maximum needed buf length is 18 @@ -190,8 +190,8 @@ func (f *fmt) fmt_unicode(u uint64) { f.zero = oldZero } -// fmt_integer formats signed and unsigned integers. -func (f *fmt) fmt_integer(u uint64, base int, isSigned bool, digits string) { +// fmtInteger formats signed and unsigned integers. +func (f *fmt) fmtInteger(u uint64, base int, isSigned bool, digits string) { negative := isSigned && int64(u) < 0 if negative { u = -u @@ -322,14 +322,14 @@ func (f *fmt) truncate(s string) string { return s } -// fmt_s formats a string. -func (f *fmt) fmt_s(s string) { +// fmtS formats a string. +func (f *fmt) fmtS(s string) { s = f.truncate(s) f.padString(s) } -// fmt_sbx formats a string or byte slice as a hexadecimal encoding of its bytes. -func (f *fmt) fmt_sbx(s string, b []byte, digits string) { +// fmtSbx formats a string or byte slice as a hexadecimal encoding of its bytes. +func (f *fmt) fmtSbx(s string, b []byte, digits string) { length := len(b) if b == nil { // No byte slice present. Assume string s should be encoded. @@ -394,20 +394,20 @@ func (f *fmt) fmt_sbx(s string, b []byte, digits string) { } } -// fmt_sx formats a string as a hexadecimal encoding of its bytes. -func (f *fmt) fmt_sx(s, digits string) { - f.fmt_sbx(s, nil, digits) +// fmtSx formats a string as a hexadecimal encoding of its bytes. +func (f *fmt) fmtSx(s, digits string) { + f.fmtSbx(s, nil, digits) } -// fmt_bx formats a byte slice as a hexadecimal encoding of its bytes. -func (f *fmt) fmt_bx(b []byte, digits string) { - f.fmt_sbx("", b, digits) +// fmtBx formats a byte slice as a hexadecimal encoding of its bytes. +func (f *fmt) fmtBx(b []byte, digits string) { + f.fmtSbx("", b, digits) } -// fmt_q formats a string as a double-quoted, escaped Go string constant. +// fmtQ formats a string as a double-quoted, escaped Go string constant. // If f.sharp is set a raw (backquoted) string may be returned instead // if the string does not contain any control characters other than tab. -func (f *fmt) fmt_q(s string) { +func (f *fmt) fmtQ(s string) { s = f.truncate(s) if f.sharp && strconv.CanBackquote(s) { f.padString("`" + s + "`") @@ -421,9 +421,9 @@ func (f *fmt) fmt_q(s string) { } } -// fmt_c formats an integer as a Unicode character. +// fmtC formats an integer as a Unicode character. // If the character is not valid Unicode, it will print '\ufffd'. -func (f *fmt) fmt_c(c uint64) { +func (f *fmt) fmtC(c uint64) { r := rune(c) if c > utf8.MaxRune { r = utf8.RuneError @@ -433,9 +433,9 @@ func (f *fmt) fmt_c(c uint64) { f.pad(buf[:w]) } -// fmt_qc formats an integer as a single-quoted, escaped Go character constant. +// fmtQc formats an integer as a single-quoted, escaped Go character constant. // If the character is not valid Unicode, it will print '\ufffd'. -func (f *fmt) fmt_qc(c uint64) { +func (f *fmt) fmtQc(c uint64) { r := rune(c) if c > utf8.MaxRune { r = utf8.RuneError @@ -448,9 +448,9 @@ func (f *fmt) fmt_qc(c uint64) { } } -// fmt_float formats a float64. It assumes that verb is a valid format specifier +// fmtFloat formats a float64. It assumes that verb is a valid format specifier // for strconv.AppendFloat and therefore fits into a byte. -func (f *fmt) fmt_float(v float64, size int, verb rune, prec int) { +func (f *fmt) fmtFloat(v float64, size int, verb rune, prec int) { // Explicit precision in format specifier overrules default precision. if f.precPresent { prec = f.prec diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go index 98c156a1217..f67f8056037 100644 --- a/libgo/go/fmt/print.go +++ b/libgo/go/fmt/print.go @@ -341,7 +341,7 @@ func (p *pp) badVerb(verb rune) { func (p *pp) fmtBool(v bool, verb rune) { switch verb { case 't', 'v': - p.fmt.fmt_boolean(v) + p.fmt.fmtBoolean(v) default: p.badVerb(verb) } @@ -352,7 +352,7 @@ func (p *pp) fmtBool(v bool, verb rune) { func (p *pp) fmt0x64(v uint64, leading0x bool) { sharp := p.fmt.sharp p.fmt.sharp = leading0x - p.fmt.fmt_integer(v, 16, unsigned, ldigits) + p.fmt.fmtInteger(v, 16, unsigned, ldigits) p.fmt.sharp = sharp } @@ -363,28 +363,28 @@ func (p *pp) fmtInteger(v uint64, isSigned bool, verb rune) { if p.fmt.sharpV && !isSigned { p.fmt0x64(v, true) } else { - p.fmt.fmt_integer(v, 10, isSigned, ldigits) + p.fmt.fmtInteger(v, 10, isSigned, ldigits) } case 'd': - p.fmt.fmt_integer(v, 10, isSigned, ldigits) + p.fmt.fmtInteger(v, 10, isSigned, ldigits) case 'b': - p.fmt.fmt_integer(v, 2, isSigned, ldigits) + p.fmt.fmtInteger(v, 2, isSigned, ldigits) case 'o': - p.fmt.fmt_integer(v, 8, isSigned, ldigits) + p.fmt.fmtInteger(v, 8, isSigned, ldigits) case 'x': - p.fmt.fmt_integer(v, 16, isSigned, ldigits) + p.fmt.fmtInteger(v, 16, isSigned, ldigits) case 'X': - p.fmt.fmt_integer(v, 16, isSigned, udigits) + p.fmt.fmtInteger(v, 16, isSigned, udigits) case 'c': - p.fmt.fmt_c(v) + p.fmt.fmtC(v) case 'q': if v <= utf8.MaxRune { - p.fmt.fmt_qc(v) + p.fmt.fmtQc(v) } else { p.badVerb(verb) } case 'U': - p.fmt.fmt_unicode(v) + p.fmt.fmtUnicode(v) default: p.badVerb(verb) } @@ -395,13 +395,13 @@ func (p *pp) fmtInteger(v uint64, isSigned bool, verb rune) { func (p *pp) fmtFloat(v float64, size int, verb rune) { switch verb { case 'v': - p.fmt.fmt_float(v, size, 'g', -1) + p.fmt.fmtFloat(v, size, 'g', -1) case 'b', 'g', 'G': - p.fmt.fmt_float(v, size, verb, -1) + p.fmt.fmtFloat(v, size, verb, -1) case 'f', 'e', 'E': - p.fmt.fmt_float(v, size, verb, 6) + p.fmt.fmtFloat(v, size, verb, 6) case 'F': - p.fmt.fmt_float(v, size, 'f', 6) + p.fmt.fmtFloat(v, size, 'f', 6) default: p.badVerb(verb) } @@ -432,18 +432,18 @@ func (p *pp) fmtString(v string, verb rune) { switch verb { case 'v': if p.fmt.sharpV { - p.fmt.fmt_q(v) + p.fmt.fmtQ(v) } else { - p.fmt.fmt_s(v) + p.fmt.fmtS(v) } case 's': - p.fmt.fmt_s(v) + p.fmt.fmtS(v) case 'x': - p.fmt.fmt_sx(v, ldigits) + p.fmt.fmtSx(v, ldigits) case 'X': - p.fmt.fmt_sx(v, udigits) + p.fmt.fmtSx(v, udigits) case 'q': - p.fmt.fmt_q(v) + p.fmt.fmtQ(v) default: p.badVerb(verb) } @@ -472,18 +472,18 @@ func (p *pp) fmtBytes(v []byte, verb rune, typeString string) { if i > 0 { p.buf.WriteByte(' ') } - p.fmt.fmt_integer(uint64(c), 10, unsigned, ldigits) + p.fmt.fmtInteger(uint64(c), 10, unsigned, ldigits) } p.buf.WriteByte(']') } case 's': - p.fmt.fmt_s(string(v)) + p.fmt.fmtS(string(v)) case 'x': - p.fmt.fmt_bx(v, ldigits) + p.fmt.fmtBx(v, ldigits) case 'X': - p.fmt.fmt_bx(v, udigits) + p.fmt.fmtBx(v, udigits) case 'q': - p.fmt.fmt_q(string(v)) + p.fmt.fmtQ(string(v)) default: p.printValue(reflect.ValueOf(v), verb, 0) } @@ -577,7 +577,7 @@ func (p *pp) handleMethods(verb rune) (handled bool) { handled = true defer p.catchPanic(p.arg, verb) // Print the result of GoString unadorned. - p.fmt.fmt_s(stringer.GoString()) + p.fmt.fmtS(stringer.GoString()) return } } else { @@ -626,7 +626,7 @@ func (p *pp) printArg(arg interface{}, verb rune) { // %T (the value's type) and %p (its address) are special; we always do them first. switch verb { case 'T': - p.fmt.fmt_s(reflect.TypeOf(arg).String()) + p.fmt.fmtS(reflect.TypeOf(arg).String()) return case 'p': p.fmtPointer(reflect.ValueOf(arg), 'p') diff --git a/libgo/go/go/ast/ast.go b/libgo/go/go/ast/ast.go index c07dd5a91ee..fd109507b8b 100644 --- a/libgo/go/go/ast/ast.go +++ b/libgo/go/go/ast/ast.go @@ -153,10 +153,12 @@ func (g *CommentGroup) Text() string { // A Field represents a Field declaration list in a struct type, // a method list in an interface type, or a parameter/result declaration // 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. // type Field struct { Doc *CommentGroup // associated documentation; or nil - Names []*Ident // field/method/parameter names; or nil if anonymous field + Names []*Ident // field/method/parameter names; or nil Type Expr // field/method/parameter type Tag *BasicLit // field tag; or nil Comment *CommentGroup // line comments; or nil @@ -207,14 +209,14 @@ func (f *FieldList) End() token.Pos { return token.NoPos } -// NumFields returns the number of (named and anonymous fields) in a FieldList. +// NumFields returns the number of parameters or struct fields represented by a FieldList. func (f *FieldList) NumFields() int { n := 0 if f != nil { for _, g := range f.List { m := len(g.Names) if m == 0 { - m = 1 // anonymous field + m = 1 } n += m } @@ -264,10 +266,11 @@ type ( // A CompositeLit node represents a composite literal. CompositeLit struct { - Type Expr // literal type; or nil - Lbrace token.Pos // position of "{" - Elts []Expr // list of composite elements; or nil - Rbrace token.Pos // position of "}" + Type Expr // literal type; or nil + Lbrace token.Pos // position of "{" + Elts []Expr // list of composite elements; or nil + Rbrace token.Pos // position of "}" + Incomplete bool // true if (source) expressions are missing in the Elts list } // A ParenExpr node represents a parenthesized expression. diff --git a/libgo/go/go/ast/filter.go b/libgo/go/go/ast/filter.go index bb571166f47..32352cb92c5 100644 --- a/libgo/go/go/ast/filter.go +++ b/libgo/go/go/ast/filter.go @@ -109,6 +109,34 @@ func filterFieldList(fields *FieldList, filter Filter, export bool) (removedFiel return } +func filterCompositeLit(lit *CompositeLit, filter Filter, export bool) { + n := len(lit.Elts) + lit.Elts = filterExprList(lit.Elts, filter, export) + if len(lit.Elts) < n { + lit.Incomplete = true + } +} + +func filterExprList(list []Expr, filter Filter, export bool) []Expr { + j := 0 + for _, exp := range list { + switch x := exp.(type) { + case *CompositeLit: + filterCompositeLit(x, filter, export) + case *KeyValueExpr: + if x, ok := x.Key.(*Ident); ok && !filter(x.Name) { + continue + } + if x, ok := x.Value.(*CompositeLit); ok { + filterCompositeLit(x, filter, export) + } + } + list[j] = exp + j++ + } + return list[0:j] +} + func filterParamList(fields *FieldList, filter Filter, export bool) bool { if fields == nil { return false @@ -158,6 +186,7 @@ func filterSpec(spec Spec, f Filter, export bool) bool { switch s := spec.(type) { case *ValueSpec: s.Names = filterIdentList(s.Names, f) + s.Values = filterExprList(s.Values, f, export) if len(s.Names) > 0 { if export { filterType(s.Type, f, export) diff --git a/libgo/go/go/build/build.go b/libgo/go/go/build/build.go index 9df4930dbcf..e067fd094f7 100644 --- a/libgo/go/go/build/build.go +++ b/libgo/go/go/build/build.go @@ -12,10 +12,12 @@ import ( "go/doc" "go/parser" "go/token" + "internal/goroot" "io" "io/ioutil" "log" "os" + "os/exec" pathpkg "path" "path/filepath" "runtime" @@ -277,6 +279,8 @@ func defaultGOPATH() string { return "" } +var defaultReleaseTags []string + func defaultContext() Context { var c Context @@ -292,11 +296,13 @@ func defaultContext() Context { // say "+build go1.x", and code that should only be built before Go 1.x // (perhaps it is the stub to use in that case) should say "+build !go1.x". // NOTE: If you add to this list, also update the doc comment in doc.go. - const version = 10 // go1.10 + const version = 11 // go1.11 for i := 1; i <= version; i++ { c.ReleaseTags = append(c.ReleaseTags, "go1."+strconv.Itoa(i)) } + defaultReleaseTags = append([]string{}, c.ReleaseTags...) // our own private copy + env := os.Getenv("CGO_ENABLED") // No defaultCGO_ENABLED in gccgo. // if env == "" { @@ -540,7 +546,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa inTestdata := func(sub string) bool { return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || strings.HasPrefix(sub, "testdata/") || sub == "testdata" } - if ctxt.GOROOT != "" && ctxt.Compiler != "gccgo" { + if ctxt.GOROOT != "" { root := ctxt.joinPath(ctxt.GOROOT, "src") if sub, ok := ctxt.hasSubdir(root, p.Dir); ok && !inTestdata(sub) { p.Goroot = true @@ -585,13 +591,19 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa return p, fmt.Errorf("import %q: cannot import absolute path", path) } + gopath := ctxt.gopath() // needed by both importGo and below; avoid computing twice + if err := ctxt.importGo(p, path, srcDir, mode, gopath); err == nil { + goto Found + } else if err != errNoModules { + return p, err + } + // tried records the location of unsuccessful package lookups var tried struct { vendor []string goroot string gopath []string } - gopath := ctxt.gopath() // Vendor directories get first chance to satisfy import. if mode&IgnoreVendor == 0 && srcDir != "" { @@ -647,7 +659,7 @@ func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Packa } tried.goroot = dir } - if ctxt.Compiler == "gccgo" && isStandardPackage(path) { + if ctxt.Compiler == "gccgo" && goroot.IsStandardPackage(ctxt.GOROOT, ctxt.Compiler, path) { p.Dir = ctxt.joinPath(ctxt.GOROOT, "src", path) p.Goroot = true p.Root = ctxt.GOROOT @@ -705,6 +717,11 @@ Found: // non-nil *Package returned when an error occurs. // We need to do this before we return early on FindOnly flag. if IsLocalImport(path) && !ctxt.isDir(p.Dir) { + if ctxt.Compiler == "gccgo" && p.Goroot { + // gccgo has no sources for GOROOT packages. + return p, nil + } + // package was not found return p, fmt.Errorf("cannot find package %q in:\n\t%s", path, p.Dir) } @@ -828,7 +845,8 @@ Found: }) p.InvalidGoFiles = append(p.InvalidGoFiles, name) } - if pf.Doc != nil && p.Doc == "" { + // 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()) } @@ -931,6 +949,116 @@ Found: return p, pkgerr } +var errNoModules = errors.New("not using modules") + +// importGo checks whether it can use the go command to find the directory for path. +// If using the go command is not appopriate, importGo returns errNoModules. +// Otherwise, importGo tries using the go command and reports whether that succeeded. +// Using the go command lets build.Import and build.Context.Import find code +// in Go modules. In the long term we want tools to use go/packages (currently golang.org/x/tools/go/packages), +// which will also use the go command. +// Invoking the go command here is not very efficient in that it computes information +// about the requested package and all dependencies and then only reports about the requested package. +// Then we reinvoke it for every dependency. But this is still better than not working at all. +// See golang.org/issue/26504. +func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode, gopath []string) error { + const debugImportGo = false + + // To invoke the go command, we must know the source directory, + // 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 srcDir == "" || 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) { + return errNoModules + } + + // If modules are not enabled, then the in-process code works fine and we should keep using it. + switch os.Getenv("GO111MODULE") { + case "off": + return errNoModules + case "on": + // ok + default: // "", "auto", anything else + // Automatic mode: no module use in $GOPATH/src. + for _, root := range gopath { + sub, ok := ctxt.hasSubdir(root, srcDir) + if ok && strings.HasPrefix(sub, "src/") { + return errNoModules + } + } + } + + // For efficiency, if path is a standard library package, let the usual lookup code handle it. + if ctxt.GOROOT != "" { + dir := ctxt.joinPath(ctxt.GOROOT, "src", path) + if ctxt.isDir(dir) { + return errNoModules + } + } + + // Look to see if there is a go.mod. + abs, err := filepath.Abs(srcDir) + if err != nil { + return errNoModules + } + for { + info, err := os.Stat(filepath.Join(abs, "go.mod")) + if err == nil && !info.IsDir() { + break + } + d := filepath.Dir(abs) + if len(d) >= len(abs) { + return errNoModules // reached top of file system, no go.mod + } + abs = d + } + + cmd := exec.Command("go", "list", "-compiler="+ctxt.Compiler, "-tags="+strings.Join(ctxt.BuildTags, ","), "-installsuffix="+ctxt.InstallSuffix, "-f={{.Dir}}\n{{.ImportPath}}\n{{.Root}}\n{{.Goroot}}\n", path) + cmd.Dir = srcDir + var stdout, stderr strings.Builder + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + cgo := "0" + if ctxt.CgoEnabled { + cgo = "1" + } + cmd.Env = append(os.Environ(), + "GOOS="+ctxt.GOOS, + "GOARCH="+ctxt.GOARCH, + "GOROOT="+ctxt.GOROOT, + "GOPATH="+ctxt.GOPATH, + "CGO_ENABLED="+cgo, + ) + + if err := cmd.Run(); err != nil { + return fmt.Errorf("go/build: importGo %s: %v\n%s\n", path, err, stderr.String()) + } + + f := strings.Split(stdout.String(), "\n") + if len(f) != 5 || f[4] != "" { + return fmt.Errorf("go/build: importGo %s: unexpected output:\n%s\n", path, stdout.String()) + } + + p.Dir = f[0] + p.ImportPath = f[1] + p.Root = f[2] + p.Goroot = f[3] == "true" + return nil +} + +func equal(x, y []string) bool { + if len(x) != len(y) { + return false + } + for i, xi := range x { + if xi != y[i] { + return false + } + } + return true +} + // hasGoFiles reports whether dir contains any files with names ending in .go. // For a vendor check we must exclude directories that contain no .go files. // Otherwise it is not possible to vendor just a/b/c and still import the @@ -1385,7 +1513,8 @@ func (ctxt *Context) makePathsAbsolute(args []string, srcDir string) { // See golang.org/issue/6038. // The @ is for OS X. See golang.org/issue/13720. // The % is for Jenkins. See golang.org/issue/16959. -const safeString = "+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$@% " +// The ! is because module paths may use them. See golang.org/issue/26716. +const safeString = "+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz:$@%! " func safeCgoName(s string) bool { if s == "" { @@ -1566,32 +1695,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]] { - if allTags != nil { - allTags[l[n-2]] = true - allTags[l[n-1]] = true - } - if l[n-1] != ctxt.GOARCH { - return false - } - if ctxt.GOOS == "android" && l[n-2] == "linux" { - return true - } - return l[n-2] == ctxt.GOOS + return ctxt.match(l[n-1], allTags) && ctxt.match(l[n-2], allTags) } - if n >= 1 && knownOS[l[n-1]] { - if allTags != nil { - allTags[l[n-1]] = true - } - if ctxt.GOOS == "android" && l[n-1] == "linux" { - return true - } - return l[n-1] == ctxt.GOOS - } - if n >= 1 && knownArch[l[n-1]] { - if allTags != nil { - allTags[l[n-1]] = true - } - return l[n-1] == ctxt.GOARCH + if n >= 1 && (knownOS[l[n-1]] || knownArch[l[n-1]]) { + return ctxt.match(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 87d8d0445e8..f21bc32b520 100644 --- a/libgo/go/go/build/build_test.go +++ b/libgo/go/go/build/build_test.go @@ -177,6 +177,18 @@ func TestShouldBuild(t *testing.T) { } } +func TestGoodOSArchFile(t *testing.T) { + ctx := &Context{BuildTags: []string{"linux"}, GOOS: "darwin"} + m := map[string]bool{} + want := map[string]bool{"linux": true} + if !ctx.goodOSArchFile("hello_linux.go", m) { + t.Errorf("goodOSArchFile(hello_linux.go) = false, want true") + } + if !reflect.DeepEqual(m, want) { + t.Errorf("goodOSArchFile(hello_linux.go) tags = %v, want %v", m, want) + } +} + type readNopCloser struct { io.Reader } @@ -397,3 +409,19 @@ func TestImportDirTarget(t *testing.T) { t.Errorf("p.PkgTargetRoot == %q, p.PkgObj == %q, want non-empty", p.PkgTargetRoot, p.PkgObj) } } + +// TestIssue23594 prevents go/build from regressing and populating Package.Doc +// from comments in test files. +func TestIssue23594(t *testing.T) { + // Package testdata/doc contains regular and external test files + // with comments attached to their package declarations. The names of the files + // ensure that we see the comments from the test files first. + p, err := ImportDir("testdata/doc", 0) + if err != nil { + t.Fatalf("could not import testdata: %v", err) + } + + if p.Doc != "Correct" { + t.Fatalf("incorrectly set .Doc to %q", p.Doc) + } +} diff --git a/libgo/go/go/build/deps_test.go b/libgo/go/go/build/deps_test.go index 6f9838b55b9..b9593787e07 100644 --- a/libgo/go/go/build/deps_test.go +++ b/libgo/go/go/build/deps_test.go @@ -36,14 +36,15 @@ var pkgDeps = map[string][]string{ // L0 is the lowest level, core, nearly unavoidable packages. "errors": {}, "io": {"errors", "sync", "sync/atomic"}, - "runtime": {"unsafe", "runtime/internal/atomic", "runtime/internal/sys"}, + "runtime": {"unsafe", "runtime/internal/atomic", "runtime/internal/sys", "internal/cpu", "internal/bytealg"}, "runtime/internal/sys": {}, "runtime/internal/atomic": {"unsafe", "runtime/internal/sys"}, "internal/race": {"runtime", "unsafe"}, "sync": {"internal/race", "runtime", "sync/atomic", "unsafe"}, "sync/atomic": {"unsafe"}, "unsafe": {}, - "internal/cpu": {"runtime"}, + "internal/cpu": {}, + "internal/bytealg": {"unsafe", "internal/cpu"}, "L0": { "errors", @@ -54,6 +55,7 @@ var pkgDeps = map[string][]string{ "sync/atomic", "unsafe", "internal/cpu", + "internal/bytealg", }, // L1 adds simple functions and strings processing, @@ -62,7 +64,7 @@ var pkgDeps = map[string][]string{ "math/bits": {}, "math/cmplx": {"math"}, "math/rand": {"L0", "math"}, - "strconv": {"L0", "unicode/utf8", "math"}, + "strconv": {"L0", "unicode/utf8", "math", "math/bits"}, "unicode/utf16": {}, "unicode/utf8": {}, @@ -97,28 +99,29 @@ var pkgDeps = map[string][]string{ // L3 adds reflection and some basic utility packages // and interface definitions, but nothing that makes // system calls. - "crypto": {"L2", "hash"}, // interfaces - "crypto/cipher": {"L2", "crypto/subtle"}, - "crypto/subtle": {}, - "encoding/base32": {"L2"}, - "encoding/base64": {"L2", "encoding/binary"}, - "encoding/binary": {"L2", "reflect"}, - "hash": {"L2"}, // interfaces - "hash/adler32": {"L2", "hash"}, - "hash/crc32": {"L2", "hash"}, - "hash/crc64": {"L2", "hash"}, - "hash/fnv": {"L2", "hash"}, - "image": {"L2", "image/color"}, // interfaces - "image/color": {"L2"}, // interfaces - "image/color/palette": {"L2", "image/color"}, - "reflect": {"L2"}, - "sort": {"reflect"}, + "crypto": {"L2", "hash"}, // interfaces + "crypto/cipher": {"L2", "crypto/subtle", "crypto/internal/subtle"}, + "crypto/internal/subtle": {"unsafe", "reflect"}, // reflect behind a appengine tag + "crypto/subtle": {}, + "encoding/base32": {"L2"}, + "encoding/base64": {"L2", "encoding/binary"}, + "encoding/binary": {"L2", "reflect"}, + "hash": {"L2"}, // interfaces + "hash/adler32": {"L2", "hash"}, + "hash/crc32": {"L2", "hash"}, + "hash/crc64": {"L2", "hash"}, + "hash/fnv": {"L2", "hash"}, + "image": {"L2", "image/color"}, // interfaces + "image/color": {"L2"}, // interfaces + "image/color/palette": {"L2", "image/color"}, + "reflect": {"L2"}, + "sort": {"reflect"}, "L3": { "L2", "crypto", "crypto/cipher", - "crypto/internal/cipherhw", + "crypto/internal/subtle", "crypto/subtle", "encoding/base32", "encoding/base64", @@ -137,7 +140,8 @@ var pkgDeps = map[string][]string{ // End of linear dependency definitions. // Operating system access. - "syscall": {"L0", "internal/race", "internal/syscall/windows/sysdll", "unicode/utf16"}, + "syscall": {"L0", "internal/race", "internal/syscall/windows/sysdll", "syscall/js", "unicode/utf16"}, + "syscall/js": {"L0"}, "internal/syscall/unix": {"L0", "syscall"}, "internal/syscall/windows": {"L0", "syscall", "internal/syscall/windows/sysdll"}, "internal/syscall/windows/registry": {"L0", "syscall", "internal/syscall/windows/sysdll", "unicode/utf16"}, @@ -156,7 +160,7 @@ var pkgDeps = map[string][]string{ "internal/poll": {"L0", "internal/race", "syscall", "time", "unicode/utf16", "unicode/utf8", "internal/syscall/windows"}, "internal/testlog": {"L0"}, - "os": {"L1", "os", "syscall", "time", "internal/poll", "internal/syscall/windows", "internal/testlog"}, + "os": {"L1", "os", "syscall", "time", "internal/poll", "internal/syscall/windows", "internal/syscall/unix", "internal/testlog"}, "path/filepath": {"L2", "os", "syscall", "internal/syscall/windows"}, "io/ioutil": {"L2", "os", "path/filepath", "time"}, "os/exec": {"L2", "os", "context", "path/filepath", "syscall"}, @@ -181,7 +185,7 @@ var pkgDeps = map[string][]string{ "regexp/syntax": {"L2"}, "runtime/debug": {"L2", "fmt", "io/ioutil", "os", "time"}, "runtime/pprof": {"L2", "compress/gzip", "context", "encoding/binary", "fmt", "io/ioutil", "os", "text/tabwriter", "time"}, - "runtime/trace": {"L0"}, + "runtime/trace": {"L0", "context", "fmt"}, "text/tabwriter": {"L2"}, "testing": {"L2", "flag", "fmt", "internal/race", "os", "runtime/debug", "runtime/pprof", "runtime/trace", "time"}, @@ -223,54 +227,54 @@ var pkgDeps = map[string][]string{ "go/importer": {"L4", "go/build", "go/internal/gccgoimporter", "go/internal/gcimporter", "go/internal/srcimporter", "go/token", "go/types"}, "go/internal/gcimporter": {"L4", "OS", "go/build", "go/constant", "go/token", "go/types", "text/scanner"}, "go/internal/gccgoimporter": {"L4", "OS", "debug/elf", "debug/xcoff", "go/constant", "go/token", "go/types", "text/scanner"}, - "go/internal/srcimporter": {"L4", "fmt", "go/ast", "go/build", "go/parser", "go/token", "go/types", "path/filepath"}, + "go/internal/srcimporter": {"L4", "OS", "fmt", "go/ast", "go/build", "go/parser", "go/token", "go/types", "path/filepath"}, "go/types": {"L4", "GOPARSER", "container/heap", "go/constant"}, // One of a kind. - "archive/tar": {"L4", "OS", "syscall", "os/user"}, - "archive/zip": {"L4", "OS", "compress/flate"}, - "container/heap": {"sort"}, - "compress/bzip2": {"L4"}, - "compress/flate": {"L4"}, - "compress/gzip": {"L4", "compress/flate"}, - "compress/lzw": {"L4"}, - "compress/zlib": {"L4", "compress/flate"}, - "context": {"errors", "fmt", "reflect", "sync", "time"}, - "database/sql": {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"}, - "database/sql/driver": {"L4", "context", "time", "database/sql/internal"}, - "debug/dwarf": {"L4"}, - "debug/elf": {"L4", "OS", "debug/dwarf", "compress/zlib"}, - "debug/gosym": {"L4"}, - "debug/macho": {"L4", "OS", "debug/dwarf"}, - "debug/pe": {"L4", "OS", "debug/dwarf"}, - "debug/plan9obj": {"L4", "OS"}, - "debug/xcoff": {"L4", "OS", "debug/dwarf"}, - "encoding": {"L4"}, - "encoding/ascii85": {"L4"}, - "encoding/asn1": {"L4", "math/big"}, - "encoding/csv": {"L4"}, - "encoding/gob": {"L4", "OS", "encoding"}, - "encoding/hex": {"L4"}, - "encoding/json": {"L4", "encoding"}, - "encoding/pem": {"L4"}, - "encoding/xml": {"L4", "encoding"}, - "flag": {"L4", "OS"}, - "go/build": {"L4", "OS", "GOPARSER"}, - "html": {"L4"}, - "image/draw": {"L4", "image/internal/imageutil"}, - "image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"}, - "image/internal/imageutil": {"L4"}, - "image/jpeg": {"L4", "image/internal/imageutil"}, - "image/png": {"L4", "compress/zlib"}, - "index/suffixarray": {"L4", "regexp"}, - "internal/singleflight": {"sync"}, - "internal/trace": {"L4", "OS"}, - "math/big": {"L4"}, - "mime": {"L4", "OS", "syscall", "internal/syscall/windows/registry"}, - "mime/quotedprintable": {"L4"}, - "net/internal/socktest": {"L4", "OS", "syscall", "internal/syscall/windows"}, - "net/url": {"L4"}, - "plugin": {"L0", "OS", "CGO"}, + "archive/tar": {"L4", "OS", "syscall", "os/user"}, + "archive/zip": {"L4", "OS", "compress/flate"}, + "container/heap": {"sort"}, + "compress/bzip2": {"L4"}, + "compress/flate": {"L4"}, + "compress/gzip": {"L4", "compress/flate"}, + "compress/lzw": {"L4"}, + "compress/zlib": {"L4", "compress/flate"}, + "context": {"errors", "fmt", "reflect", "sync", "time"}, + "database/sql": {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"}, + "database/sql/driver": {"L4", "context", "time", "database/sql/internal"}, + "debug/dwarf": {"L4"}, + "debug/elf": {"L4", "OS", "debug/dwarf", "compress/zlib"}, + "debug/gosym": {"L4"}, + "debug/macho": {"L4", "OS", "debug/dwarf", "compress/zlib"}, + "debug/pe": {"L4", "OS", "debug/dwarf", "compress/zlib"}, + "debug/plan9obj": {"L4", "OS"}, + "debug/xcoff": {"L4", "OS", "debug/dwarf"}, + "encoding": {"L4"}, + "encoding/ascii85": {"L4"}, + "encoding/asn1": {"L4", "math/big"}, + "encoding/csv": {"L4"}, + "encoding/gob": {"L4", "OS", "encoding"}, + "encoding/hex": {"L4"}, + "encoding/json": {"L4", "encoding"}, + "encoding/pem": {"L4"}, + "encoding/xml": {"L4", "encoding"}, + "flag": {"L4", "OS"}, + "go/build": {"L4", "OS", "GOPARSER"}, + "html": {"L4"}, + "image/draw": {"L4", "image/internal/imageutil"}, + "image/gif": {"L4", "compress/lzw", "image/color/palette", "image/draw"}, + "image/internal/imageutil": {"L4"}, + "image/jpeg": {"L4", "image/internal/imageutil"}, + "image/png": {"L4", "compress/zlib"}, + "index/suffixarray": {"L4", "regexp"}, + "internal/singleflight": {"sync"}, + "internal/trace": {"L4", "OS"}, + "math/big": {"L4"}, + "mime": {"L4", "OS", "syscall", "internal/syscall/windows/registry"}, + "mime/quotedprintable": {"L4"}, + "net/internal/socktest": {"L4", "OS", "syscall", "internal/syscall/windows"}, + "net/url": {"L4"}, + "plugin": {"L0", "OS", "CGO"}, "runtime/pprof/internal/profile": {"L4", "OS", "compress/gzip", "regexp"}, "testing/internal/testdeps": {"L4", "internal/testlog", "runtime/pprof", "regexp"}, "text/scanner": {"L4", "OS"}, @@ -299,7 +303,7 @@ var pkgDeps = map[string][]string{ "runtime/msan": {"C"}, // Plan 9 alone needs io/ioutil and os. - "os/user": {"L4", "CGO", "io/ioutil", "os", "syscall"}, + "os/user": {"L4", "CGO", "io/ioutil", "os", "syscall", "internal/syscall/windows", "internal/syscall/windows/registry"}, // Internal package used only for testing. "os/signal/internal/pty": {"CGO", "fmt", "os", "syscall"}, @@ -312,7 +316,7 @@ var pkgDeps = map[string][]string{ "context", "math/rand", "os", "reflect", "sort", "syscall", "time", "internal/nettrace", "internal/poll", "internal/syscall/windows", "internal/singleflight", "internal/race", - "golang_org/x/net/lif", "golang_org/x/net/route", + "golang_org/x/net/dns/dnsmessage", "golang_org/x/net/lif", "golang_org/x/net/route", }, // NET enables use of basic network-related packages. @@ -329,19 +333,21 @@ var pkgDeps = map[string][]string{ "net/textproto": {"L4", "OS", "net"}, // Core crypto. - "crypto/aes": {"L3"}, - "crypto/des": {"L3"}, - "crypto/hmac": {"L3"}, - "crypto/md5": {"L3"}, - "crypto/rc4": {"L3"}, - "crypto/sha1": {"L3"}, - "crypto/sha256": {"L3"}, - "crypto/sha512": {"L3"}, + "crypto/aes": {"L3"}, + "crypto/des": {"L3"}, + "crypto/hmac": {"L3"}, + "crypto/internal/randutil": {"io", "sync"}, + "crypto/md5": {"L3"}, + "crypto/rc4": {"L3"}, + "crypto/sha1": {"L3"}, + "crypto/sha256": {"L3"}, + "crypto/sha512": {"L3"}, "CRYPTO": { "crypto/aes", "crypto/des", "crypto/hmac", + "crypto/internal/randutil", "crypto/md5", "crypto/rc4", "crypto/sha1", @@ -355,7 +361,7 @@ var pkgDeps = map[string][]string{ // Random byte, number generation. // This would be part of core crypto except that it imports // math/big, which imports fmt. - "crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall", "internal/syscall/unix"}, + "crypto/rand": {"L4", "CRYPTO", "OS", "math/big", "syscall", "syscall/js", "internal/syscall/unix"}, // Mathematical crypto: dependencies on fmt (L4) and math/big. // We could avoid some of the fmt, but math/big imports fmt anyway. @@ -399,10 +405,10 @@ var pkgDeps = map[string][]string{ "context", "crypto/rand", "crypto/tls", + "golang_org/x/net/http/httpguts", + "golang_org/x/net/http/httpproxy", "golang_org/x/net/http2/hpack", "golang_org/x/net/idna", - "golang_org/x/net/lex/httplex", - "golang_org/x/net/proxy", "golang_org/x/text/unicode/norm", "golang_org/x/text/width", "internal/nettrace", @@ -410,20 +416,24 @@ var pkgDeps = map[string][]string{ "net/http/httptrace", "net/http/internal", "runtime/debug", + "syscall/js", }, "net/http/internal": {"L4"}, - "net/http/httptrace": {"context", "crypto/tls", "internal/nettrace", "net", "reflect", "time"}, + "net/http/httptrace": {"context", "crypto/tls", "internal/nettrace", "net", "net/textproto", "reflect", "time"}, // HTTP-using packages. "expvar": {"L4", "OS", "encoding/json", "net/http"}, "net/http/cgi": {"L4", "NET", "OS", "crypto/tls", "net/http", "regexp"}, "net/http/cookiejar": {"L4", "NET", "net/http"}, "net/http/fcgi": {"L4", "NET", "OS", "context", "net/http", "net/http/cgi"}, - "net/http/httptest": {"L4", "NET", "OS", "crypto/tls", "flag", "net/http", "net/http/internal", "crypto/x509"}, - "net/http/httputil": {"L4", "NET", "OS", "context", "net/http", "net/http/internal"}, - "net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof", "runtime/trace"}, - "net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"}, - "net/rpc/jsonrpc": {"L4", "NET", "encoding/json", "net/rpc"}, + "net/http/httptest": { + "L4", "NET", "OS", "crypto/tls", "flag", "net/http", "net/http/internal", "crypto/x509", + "golang_org/x/net/http/httpguts", + }, + "net/http/httputil": {"L4", "NET", "OS", "context", "net/http", "net/http/internal"}, + "net/http/pprof": {"L4", "OS", "html/template", "net/http", "runtime/pprof", "runtime/trace"}, + "net/rpc": {"L4", "NET", "encoding/gob", "html/template", "net/http"}, + "net/rpc/jsonrpc": {"L4", "NET", "encoding/json", "net/rpc"}, } // isMacro reports whether p is a package dependency macro diff --git a/libgo/go/go/build/doc.go b/libgo/go/go/build/doc.go index daa9a756714..69613e359c2 100644 --- a/libgo/go/go/build/doc.go +++ b/libgo/go/go/build/doc.go @@ -107,6 +107,7 @@ // - "go1.8", from Go version 1.8 onward // - "go1.9", from Go version 1.9 onward // - "go1.10", from Go version 1.10 onward +// - "go1.11", from Go version 1.11 onward // - any additional words listed in ctxt.BuildTags // // If a file's name, after stripping the extension and a possible _test suffix, diff --git a/libgo/go/go/build/gc.go b/libgo/go/go/build/gc.go index e2be2cbb1d1..3025cd56815 100644 --- a/libgo/go/go/build/gc.go +++ b/libgo/go/go/build/gc.go @@ -7,131 +7,11 @@ package build import ( - "os" - "os/exec" "path/filepath" "runtime" - "strings" - "sync" ) // getToolDir returns the default value of ToolDir. func getToolDir() string { return filepath.Join(runtime.GOROOT(), "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH) } - -// isStandardPackage is not used for the gc toolchain. -// However, this function may be called when using `go build -compiler=gccgo`. -func isStandardPackage(path string) bool { - return gccgoSearch.isStandard(path) -} - -// gccgoSearch holds the gccgo search directories. -type gccgoDirs struct { - once sync.Once - dirs []string -} - -// gccgoSearch is used to check whether a gccgo package exists in the -// standard library. -var gccgoSearch gccgoDirs - -// init finds the gccgo search directories. If this fails it leaves dirs == nil. -func (gd *gccgoDirs) init() { - gccgo := os.Getenv("GCCGO") - if gccgo == "" { - gccgo = "gccgo" - } - bin, err := exec.LookPath(gccgo) - if err != nil { - return - } - - allDirs, err := exec.Command(bin, "-print-search-dirs").Output() - if err != nil { - return - } - versionB, err := exec.Command(bin, "-dumpversion").Output() - if err != nil { - return - } - version := strings.TrimSpace(string(versionB)) - machineB, err := exec.Command(bin, "-dumpmachine").Output() - if err != nil { - return - } - machine := strings.TrimSpace(string(machineB)) - - dirsEntries := strings.Split(string(allDirs), "\n") - const prefix = "libraries: =" - var dirs []string - for _, dirEntry := range dirsEntries { - if strings.HasPrefix(dirEntry, prefix) { - dirs = filepath.SplitList(strings.TrimPrefix(dirEntry, prefix)) - break - } - } - if len(dirs) == 0 { - return - } - - var lastDirs []string - for _, dir := range dirs { - goDir := filepath.Join(dir, "go", version) - if fi, err := os.Stat(goDir); err == nil && fi.IsDir() { - gd.dirs = append(gd.dirs, goDir) - goDir = filepath.Join(goDir, machine) - if fi, err = os.Stat(goDir); err == nil && fi.IsDir() { - gd.dirs = append(gd.dirs, goDir) - } - } - if fi, err := os.Stat(dir); err == nil && fi.IsDir() { - lastDirs = append(lastDirs, dir) - } - } - gd.dirs = append(gd.dirs, lastDirs...) -} - -// isStandard returns whether path is a standard library for gccgo. -func (gd *gccgoDirs) isStandard(path string) bool { - // Quick check: if the first path component has a '.', it's not - // in the standard library. This skips most GOPATH directories. - i := strings.Index(path, "/") - if i < 0 { - i = len(path) - } - if strings.Contains(path[:i], ".") { - return false - } - - if path == "unsafe" { - // Special case. - return true - } - - gd.once.Do(gd.init) - if gd.dirs == nil { - // We couldn't find the gccgo search directories. - // Best guess, since the first component did not contain - // '.', is that this is a standard library package. - return true - } - - for _, dir := range gd.dirs { - full := filepath.Join(dir, path) - pkgdir, pkg := filepath.Split(full) - for _, p := range [...]string{ - full, - full + ".gox", - pkgdir + "lib" + pkg + ".so", - pkgdir + "lib" + pkg + ".a", - full + ".o", - } { - if fi, err := os.Stat(p); err == nil && !fi.IsDir() { - return true - } - } - } - - return false -} diff --git a/libgo/go/go/build/gccgo.go b/libgo/go/go/build/gccgo.go index 59e089d69db..c6aac9aa1bc 100644 --- a/libgo/go/go/build/gccgo.go +++ b/libgo/go/go/build/gccgo.go @@ -12,9 +12,3 @@ import "runtime" func getToolDir() string { return envOr("GCCGOTOOLDIR", runtime.GCCGOTOOLDIR) } - -// isStandardPackage returns whether path names a standard library package. -// This uses a list generated at build time. -func isStandardPackage(path string) bool { - return stdpkg[path] -} diff --git a/libgo/go/go/build/testdata/doc/a_test.go b/libgo/go/go/build/testdata/doc/a_test.go new file mode 100644 index 00000000000..1c07b56360d --- /dev/null +++ b/libgo/go/go/build/testdata/doc/a_test.go @@ -0,0 +1,2 @@ +// Doc from xtests +package doc_test diff --git a/libgo/go/go/build/testdata/doc/b_test.go b/libgo/go/go/build/testdata/doc/b_test.go new file mode 100644 index 00000000000..0cf1605ef34 --- /dev/null +++ b/libgo/go/go/build/testdata/doc/b_test.go @@ -0,0 +1 @@ +package doc_test diff --git a/libgo/go/go/build/testdata/doc/c_test.go b/libgo/go/go/build/testdata/doc/c_test.go new file mode 100644 index 00000000000..10257070799 --- /dev/null +++ b/libgo/go/go/build/testdata/doc/c_test.go @@ -0,0 +1 @@ +package doc diff --git a/libgo/go/go/build/testdata/doc/d_test.go b/libgo/go/go/build/testdata/doc/d_test.go new file mode 100644 index 00000000000..ec19564eb30 --- /dev/null +++ b/libgo/go/go/build/testdata/doc/d_test.go @@ -0,0 +1,2 @@ +// Doc from regular tests. +package doc diff --git a/libgo/go/go/build/testdata/doc/e.go b/libgo/go/go/build/testdata/doc/e.go new file mode 100644 index 00000000000..10257070799 --- /dev/null +++ b/libgo/go/go/build/testdata/doc/e.go @@ -0,0 +1 @@ +package doc diff --git a/libgo/go/go/build/testdata/doc/f.go b/libgo/go/go/build/testdata/doc/f.go new file mode 100644 index 00000000000..ab1d0bc9352 --- /dev/null +++ b/libgo/go/go/build/testdata/doc/f.go @@ -0,0 +1,2 @@ +// Correct +package doc diff --git a/libgo/go/go/constant/example_test.go b/libgo/go/go/constant/example_test.go new file mode 100644 index 00000000000..21f9de7bf58 --- /dev/null +++ b/libgo/go/go/constant/example_test.go @@ -0,0 +1,160 @@ +// 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 gccgo_examples + +package constant_test + +import ( + "fmt" + "go/constant" + "go/token" + "sort" +) + +func Example_complexNumbers() { + // Create the complex number 2.3 + 5i. + ar := constant.MakeFloat64(2.3) + ai := constant.MakeImag(constant.MakeInt64(5)) + a := constant.BinaryOp(ar, token.ADD, ai) + + // Compute (2.3 + 5i) * 11. + b := constant.MakeUint64(11) + c := constant.BinaryOp(a, token.MUL, b) + + // Convert c into a complex128. + Ar, exact := constant.Float64Val(constant.Real(c)) + if !exact { + fmt.Printf("Could not represent real part %s exactly as float64\n", constant.Real(c)) + } + Ai, exact := constant.Float64Val(constant.Imag(c)) + if !exact { + fmt.Printf("Could not represent imaginary part %s as exactly as float64\n", constant.Imag(c)) + } + C := complex(Ar, Ai) + + fmt.Println("literal", 25.3+55i) + fmt.Println("go/constant", c) + fmt.Println("complex128", C) + + // Output: + // + // Could not represent real part 25.3 exactly as float64 + // literal (25.3+55i) + // go/constant (25.3 + 55i) + // complex128 (25.299999999999997+55i) +} + +func ExampleBinaryOp() { + // 11 / 0.5 + a := constant.MakeUint64(11) + b := constant.MakeFloat64(0.5) + c := constant.BinaryOp(a, token.QUO, b) + fmt.Println(c) + + // Output: 22 +} + +func ExampleUnaryOp() { + vs := []constant.Value{ + constant.MakeBool(true), + constant.MakeFloat64(2.7), + constant.MakeUint64(42), + } + + for i, v := range vs { + switch v.Kind() { + case constant.Bool: + vs[i] = constant.UnaryOp(token.NOT, v, 0) + + case constant.Float: + vs[i] = constant.UnaryOp(token.SUB, v, 0) + + case constant.Int: + // Use 16-bit precision. + // This would be equivalent to ^uint16(v). + vs[i] = constant.UnaryOp(token.XOR, v, 16) + } + } + + for _, v := range vs { + fmt.Println(v) + } + + // Output: + // + // false + // -2.7 + // 65493 +} + +func ExampleCompare() { + vs := []constant.Value{ + constant.MakeString("Z"), + constant.MakeString("bacon"), + constant.MakeString("go"), + constant.MakeString("Frame"), + constant.MakeString("defer"), + constant.MakeFromLiteral(`"a"`, token.STRING, 0), + } + + sort.Slice(vs, func(i, j int) bool { + // Equivalent to vs[i] <= vs[j]. + return constant.Compare(vs[i], token.LEQ, vs[j]) + }) + + for _, v := range vs { + fmt.Println(constant.StringVal(v)) + } + + // Output: + // + // Frame + // Z + // a + // bacon + // defer + // go +} + +func ExampleSign() { + zero := constant.MakeInt64(0) + one := constant.MakeInt64(1) + negOne := constant.MakeInt64(-1) + + mkComplex := func(a, b constant.Value) constant.Value { + b = constant.MakeImag(b) + return constant.BinaryOp(a, token.ADD, b) + } + + vs := []constant.Value{ + negOne, + mkComplex(zero, negOne), + mkComplex(one, negOne), + mkComplex(negOne, one), + mkComplex(negOne, negOne), + zero, + mkComplex(zero, zero), + one, + mkComplex(zero, one), + mkComplex(one, one), + } + + for _, v := range vs { + fmt.Printf("% d %s\n", constant.Sign(v), v) + } + + // Output: + // + // -1 -1 + // -1 (0 + -1i) + // -1 (1 + -1i) + // -1 (-1 + 1i) + // -1 (-1 + -1i) + // 0 0 + // 0 (0 + 0i) + // 1 1 + // 1 (0 + 1i) + // 1 (1 + 1i) +} diff --git a/libgo/go/go/constant/value_test.go b/libgo/go/go/constant/value_test.go index 5ec4f4c4185..e6fca76e182 100644 --- a/libgo/go/go/constant/value_test.go +++ b/libgo/go/go/constant/value_test.go @@ -431,6 +431,7 @@ func TestUnknown(t *testing.T) { MakeBool(false), // token.ADD ok below, operation is never considered MakeString(""), MakeInt64(1), + MakeFromLiteral("''", token.CHAR, 0), MakeFromLiteral("-1234567890123456789012345678901234567890", token.INT, 0), MakeFloat64(1.2), MakeImag(MakeFloat64(1.2)), diff --git a/libgo/go/go/doc/comment.go b/libgo/go/go/doc/comment.go index 4228e8cd9c5..a7430f45cb9 100644 --- a/libgo/go/go/doc/comment.go +++ b/libgo/go/go/doc/comment.go @@ -231,8 +231,8 @@ func heading(line string) string { return "" } - // exclude lines with illegal characters - if strings.ContainsAny(line, ",.;:!?+*/=()[]{}_^°&§~%#@<\">\\") { + // exclude lines with illegal characters. we allow "()," + if strings.ContainsAny(line, ";:!?+*/=[]{}_^°&§~%#@<\">\\") { return "" } @@ -248,6 +248,18 @@ func heading(line string) string { b = b[i+2:] } + // allow "." when followed by non-space + for b := line; ; { + i := strings.IndexRune(b, '.') + if i < 0 { + break + } + if i+1 >= len(b) || b[i+1] == ' ' { + return "" // not followed by non-space + } + b = b[i+1:] + } + return line } @@ -281,7 +293,7 @@ func anchorID(line string) string { // a single paragraph. There is one exception to the rule: a span that // consists of a single line, is followed by another paragraph span, // begins with a capital letter, and contains no punctuation -// is formatted as a heading. +// other than parentheses and commas is formatted as a heading. // // A span of indented lines is converted into a
 block,
 // with the common indent prefix removed.
diff --git a/libgo/go/go/doc/example.go b/libgo/go/go/doc/example.go
index a89f29b40f4..5b40bb0fb25 100644
--- a/libgo/go/go/doc/example.go
+++ b/libgo/go/go/doc/example.go
@@ -56,7 +56,7 @@ func Examples(files ...*ast.File) []*Example {
 				continue
 			}
 			f, ok := decl.(*ast.FuncDecl)
-			if !ok {
+			if !ok || f.Recv != nil {
 				continue
 			}
 			numDecl++
@@ -77,7 +77,7 @@ func Examples(files ...*ast.File) []*Example {
 				Name:        name[len("Example"):],
 				Doc:         doc,
 				Code:        f.Body,
-				Play:        playExample(file, f.Body),
+				Play:        playExample(file, f),
 				Comments:    file.Comments,
 				Output:      output,
 				Unordered:   unordered,
@@ -140,27 +140,39 @@ func isTest(name, prefix string) bool {
 
 // playExample synthesizes a new *ast.File based on the provided
 // file with the provided function body as the body of main.
-func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
+func playExample(file *ast.File, f *ast.FuncDecl) *ast.File {
+	body := f.Body
+
 	if !strings.HasSuffix(file.Name.Name, "_test") {
 		// We don't support examples that are part of the
 		// greater package (yet).
 		return nil
 	}
 
-	// Find top-level declarations in the file.
-	topDecls := make(map[*ast.Object]bool)
+	// Collect top-level declarations in the file.
+	topDecls := make(map[*ast.Object]ast.Decl)
+	typMethods := make(map[string][]ast.Decl)
+
 	for _, decl := range file.Decls {
 		switch d := decl.(type) {
 		case *ast.FuncDecl:
-			topDecls[d.Name.Obj] = true
+			if d.Recv == nil {
+				topDecls[d.Name.Obj] = d
+			} else {
+				if len(d.Recv.List) == 1 {
+					t := d.Recv.List[0].Type
+					tname, _ := baseTypeName(t)
+					typMethods[tname] = append(typMethods[tname], d)
+				}
+			}
 		case *ast.GenDecl:
 			for _, spec := range d.Specs {
 				switch s := spec.(type) {
 				case *ast.TypeSpec:
-					topDecls[s.Name.Obj] = true
+					topDecls[s.Name.Obj] = d
 				case *ast.ValueSpec:
-					for _, id := range s.Names {
-						topDecls[id.Obj] = true
+					for _, name := range s.Names {
+						topDecls[name.Obj] = d
 					}
 				}
 			}
@@ -169,36 +181,59 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
 
 	// Find unresolved identifiers and uses of top-level declarations.
 	unresolved := make(map[string]bool)
-	usesTopDecl := false
+	var depDecls []ast.Decl
+	hasDepDecls := make(map[ast.Decl]bool)
+
 	var inspectFunc func(ast.Node) bool
 	inspectFunc = func(n ast.Node) bool {
-		// For selector expressions, only inspect the left hand side.
-		// (For an expression like fmt.Println, only add "fmt" to the
-		// set of unresolved names, not "Println".)
-		if e, ok := n.(*ast.SelectorExpr); ok {
+		switch e := n.(type) {
+		case *ast.Ident:
+			if e.Obj == nil && e.Name != "_" {
+				unresolved[e.Name] = true
+			} else if d := topDecls[e.Obj]; d != nil {
+				if !hasDepDecls[d] {
+					hasDepDecls[d] = true
+					depDecls = append(depDecls, d)
+				}
+			}
+			return true
+		case *ast.SelectorExpr:
+			// For selector expressions, only inspect the left hand side.
+			// (For an expression like fmt.Println, only add "fmt" to the
+			// set of unresolved names, not "Println".)
 			ast.Inspect(e.X, inspectFunc)
 			return false
-		}
-		// For key value expressions, only inspect the value
-		// as the key should be resolved by the type of the
-		// composite literal.
-		if e, ok := n.(*ast.KeyValueExpr); ok {
+		case *ast.KeyValueExpr:
+			// For key value expressions, only inspect the value
+			// as the key should be resolved by the type of the
+			// composite literal.
 			ast.Inspect(e.Value, inspectFunc)
 			return false
 		}
-		if id, ok := n.(*ast.Ident); ok {
-			if id.Obj == nil {
-				unresolved[id.Name] = true
-			} else if topDecls[id.Obj] {
-				usesTopDecl = true
-			}
-		}
 		return true
 	}
 	ast.Inspect(body, inspectFunc)
-	if usesTopDecl {
-		// We don't support examples that are not self-contained (yet).
-		return nil
+	for i := 0; i < len(depDecls); i++ {
+		switch d := depDecls[i].(type) {
+		case *ast.FuncDecl:
+			ast.Inspect(d.Body, inspectFunc)
+		case *ast.GenDecl:
+			for _, spec := range d.Specs {
+				switch s := spec.(type) {
+				case *ast.TypeSpec:
+					ast.Inspect(s.Type, inspectFunc)
+
+					depDecls = append(depDecls, typMethods[s.Name.Name]...)
+				case *ast.ValueSpec:
+					if s.Type != nil {
+						ast.Inspect(s.Type, inspectFunc)
+					}
+					for _, val := range s.Values {
+						ast.Inspect(val, inspectFunc)
+					}
+				}
+			}
+		}
 	}
 
 	// Remove predeclared identifiers from unresolved list.
@@ -261,6 +296,20 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
 	// end position.
 	body, comments = stripOutputComment(body, comments)
 
+	// Include documentation belonging to dependent declarations.
+	for _, d := range depDecls {
+		switch d := d.(type) {
+		case *ast.GenDecl:
+			if d.Doc != nil {
+				comments = append(comments, d.Doc)
+			}
+		case *ast.FuncDecl:
+			if d.Doc != nil {
+				comments = append(comments, d.Doc)
+			}
+		}
+	}
+
 	// Synthesize import declaration.
 	importDecl := &ast.GenDecl{
 		Tok:    token.IMPORT,
@@ -279,14 +328,27 @@ func playExample(file *ast.File, body *ast.BlockStmt) *ast.File {
 	// Synthesize main function.
 	funcDecl := &ast.FuncDecl{
 		Name: ast.NewIdent("main"),
-		Type: &ast.FuncType{Params: &ast.FieldList{}}, // FuncType.Params must be non-nil
+		Type: f.Type,
 		Body: body,
 	}
 
+	decls := make([]ast.Decl, 0, 2+len(depDecls))
+	decls = append(decls, importDecl)
+	decls = append(decls, depDecls...)
+	decls = append(decls, funcDecl)
+
+	sort.Slice(decls, func(i, j int) bool {
+		return decls[i].Pos() < decls[j].Pos()
+	})
+
+	sort.Slice(comments, func(i, j int) bool {
+		return comments[i].Pos() < comments[j].Pos()
+	})
+
 	// Synthesize file.
 	return &ast.File{
 		Name:     ast.NewIdent("main"),
-		Decls:    []ast.Decl{importDecl, funcDecl},
+		Decls:    decls,
 		Comments: comments,
 	}
 }
diff --git a/libgo/go/go/doc/example_test.go b/libgo/go/go/doc/example_test.go
index e154ea8bfc5..552a51bf742 100644
--- a/libgo/go/go/doc/example_test.go
+++ b/libgo/go/go/doc/example_test.go
@@ -6,6 +6,7 @@ package doc_test
 
 import (
 	"bytes"
+	"go/ast"
 	"go/doc"
 	"go/format"
 	"go/parser"
@@ -21,6 +22,7 @@ import (
 	"flag"
 	"fmt"
 	"log"
+	"sort"
 	"os/exec"
 )
 
@@ -67,6 +69,46 @@ var keyValueTopDecl = struct {
 
 func ExampleKeyValueTopDecl() {
 	fmt.Print(keyValueTopDecl)
+	// Output: a: "B", b: 2
+}
+
+// Person represents a person by name and age.
+type Person struct {
+    Name string
+    Age  int
+}
+
+// String returns a string representation of the Person.
+func (p Person) String() string {
+    return fmt.Sprintf("%s: %d", p.Name, p.Age)
+}
+
+// ByAge implements sort.Interface for []Person based on
+// the Age field.
+type ByAge []Person
+
+// Len returns the number of elements in ByAge.
+func (a (ByAge)) Len() int { return len(a) }
+
+// Swap swaps the elements in ByAge.
+func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
+
+// people is the array of Person
+var people = []Person{
+	{"Bob", 31},
+	{"John", 42},
+	{"Michael", 17},
+	{"Jenny", 26},
+}
+
+func ExampleSort() {
+    fmt.Println(people)
+    sort.Sort(ByAge(people))
+    fmt.Println(people)
+    // Output:
+    // [Bob: 31 John: 42 Michael: 17 Jenny: 26]
+    // [Michael: 17 Jenny: 26 Bob: 31 John: 42]
 }
 `
 
@@ -93,8 +135,14 @@ var exampleTestCases = []struct {
 		Output: "Name: \"play\"\n",
 	},
 	{
-		Name: "KeyValueTopDecl",
-		Play: "",
+		Name:   "KeyValueTopDecl",
+		Play:   exampleKeyValueTopDeclPlay,
+		Output: "a: \"B\", b: 2\n",
+	},
+	{
+		Name:   "Sort",
+		Play:   exampleSortPlay,
+		Output: "[Bob: 31 John: 42 Michael: 17 Jenny: 26]\n[Michael: 17 Jenny: 26 Bob: 31 John: 42]\n",
 	},
 }
 
@@ -158,6 +206,69 @@ func main() {
 }
 `
 
+const exampleKeyValueTopDeclPlay = `package main
+
+import (
+	"fmt"
+)
+
+var keyValueTopDecl = struct {
+	a string
+	b int
+}{
+	a: "B",
+	b: 2,
+}
+
+func main() {
+	fmt.Print(keyValueTopDecl)
+}
+`
+
+const exampleSortPlay = `package main
+
+import (
+	"fmt"
+	"sort"
+)
+
+// Person represents a person by name and age.
+type Person struct {
+	Name string
+	Age  int
+}
+
+// String returns a string representation of the Person.
+func (p Person) String() string {
+	return fmt.Sprintf("%s: %d", p.Name, p.Age)
+}
+
+// ByAge implements sort.Interface for []Person based on
+// the Age field.
+type ByAge []Person
+
+// Len returns the number of elements in ByAge.
+func (a ByAge) Len() int { return len(a) }
+
+// Swap swaps the elements in ByAge.
+func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
+
+// people is the array of Person
+var people = []Person{
+	{"Bob", 31},
+	{"John", 42},
+	{"Michael", 17},
+	{"Jenny", 26},
+}
+
+func main() {
+	fmt.Println(people)
+	sort.Sort(ByAge(people))
+	fmt.Println(people)
+}
+`
+
 func TestExamples(t *testing.T) {
 	fset := token.NewFileSet()
 	file, err := parser.ParseFile(fset, "test.go", strings.NewReader(exampleTestFile), parser.ParseComments)
@@ -170,16 +281,7 @@ func TestExamples(t *testing.T) {
 			t.Errorf("got Name == %q, want %q", e.Name, c.Name)
 		}
 		if w := c.Play; w != "" {
-			var g string // hah
-			if e.Play == nil {
-				g = ""
-			} else {
-				var buf bytes.Buffer
-				if err := format.Node(&buf, fset, e.Play); err != nil {
-					t.Fatal(err)
-				}
-				g = buf.String()
-			}
+			g := formatFile(t, fset, e.Play)
 			if g != w {
 				t.Errorf("%s: got Play == %q, want %q", c.Name, g, w)
 			}
@@ -189,3 +291,73 @@ func TestExamples(t *testing.T) {
 		}
 	}
 }
+
+const exampleWholeFile = `package foo_test
+
+type X int
+
+func (X) Foo() {
+}
+
+func (X) TestBlah() {
+}
+
+func (X) BenchmarkFoo() {
+}
+
+func Example() {
+	fmt.Println("Hello, world!")
+	// Output: Hello, world!
+}
+`
+
+const exampleWholeFileOutput = `package main
+
+type X int
+
+func (X) Foo() {
+}
+
+func (X) TestBlah() {
+}
+
+func (X) BenchmarkFoo() {
+}
+
+func main() {
+	fmt.Println("Hello, world!")
+}
+`
+
+func TestExamplesWholeFile(t *testing.T) {
+	fset := token.NewFileSet()
+	file, err := parser.ParseFile(fset, "test.go", strings.NewReader(exampleWholeFile), parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+	es := doc.Examples(file)
+	if len(es) != 1 {
+		t.Fatalf("wrong number of examples; got %d want 1", len(es))
+	}
+	e := es[0]
+	if e.Name != "" {
+		t.Errorf("got Name == %q, want %q", e.Name, "")
+	}
+	if g, w := formatFile(t, fset, e.Play), exampleWholeFileOutput; g != w {
+		t.Errorf("got Play == %q, want %q", g, w)
+	}
+	if g, w := e.Output, "Hello, world!\n"; g != w {
+		t.Errorf("got Output == %q, want %q", g, w)
+	}
+}
+
+func formatFile(t *testing.T, fset *token.FileSet, n *ast.File) string {
+	if n == nil {
+		return ""
+	}
+	var buf bytes.Buffer
+	if err := format.Node(&buf, fset, n); err != nil {
+		t.Fatal(err)
+	}
+	return buf.String()
+}
diff --git a/libgo/go/go/doc/exports.go b/libgo/go/go/doc/exports.go
index 40cbb22797e..5f99bf7772c 100644
--- a/libgo/go/go/doc/exports.go
+++ b/libgo/go/go/doc/exports.go
@@ -25,6 +25,49 @@ func filterIdentList(list []*ast.Ident) []*ast.Ident {
 	return list[0:j]
 }
 
+var underscore = ast.NewIdent("_")
+
+func filterCompositeLit(lit *ast.CompositeLit, filter Filter, export bool) {
+	n := len(lit.Elts)
+	lit.Elts = filterExprList(lit.Elts, filter, export)
+	if len(lit.Elts) < n {
+		lit.Incomplete = true
+	}
+}
+
+func filterExprList(list []ast.Expr, filter Filter, export bool) []ast.Expr {
+	j := 0
+	for _, exp := range list {
+		switch x := exp.(type) {
+		case *ast.CompositeLit:
+			filterCompositeLit(x, filter, export)
+		case *ast.KeyValueExpr:
+			if x, ok := x.Key.(*ast.Ident); ok && !filter(x.Name) {
+				continue
+			}
+			if x, ok := x.Value.(*ast.CompositeLit); ok {
+				filterCompositeLit(x, filter, export)
+			}
+		}
+		list[j] = exp
+		j++
+	}
+	return list[0:j]
+}
+
+// updateIdentList replaces all unexported identifiers with underscore
+// and reports whether at least one exported name exists.
+func updateIdentList(list []*ast.Ident) (hasExported bool) {
+	for i, x := range list {
+		if ast.IsExported(x.Name) {
+			hasExported = true
+		} else {
+			list[i] = underscore
+		}
+	}
+	return hasExported
+}
+
 // hasExportedName reports whether list contains any exported names.
 //
 func hasExportedName(list []*ast.Ident) bool {
@@ -156,10 +199,24 @@ func (r *reader) filterSpec(spec ast.Spec) bool {
 		// always keep imports so we can collect them
 		return true
 	case *ast.ValueSpec:
-		s.Names = filterIdentList(s.Names)
-		if len(s.Names) > 0 {
-			r.filterType(nil, s.Type)
-			return true
+		s.Values = filterExprList(s.Values, ast.IsExported, true)
+		if len(s.Values) > 0 || s.Type == nil && len(s.Values) == 0 {
+			// If there are values declared on RHS, just replace the unexported
+			// identifiers on the LHS with underscore, so that it matches
+			// the sequence of expression on the RHS.
+			//
+			// Similarly, if there are no type and values, then this expression
+			// must be following an iota expression, where order matters.
+			if updateIdentList(s.Names) {
+				r.filterType(nil, s.Type)
+				return true
+			}
+		} else {
+			s.Names = filterIdentList(s.Names)
+			if len(s.Names) > 0 {
+				r.filterType(nil, s.Type)
+				return true
+			}
 		}
 	case *ast.TypeSpec:
 		if name := s.Name.Name; ast.IsExported(name) {
diff --git a/libgo/go/go/doc/reader.go b/libgo/go/go/doc/reader.go
index 140f5872336..21c02920aba 100644
--- a/libgo/go/go/doc/reader.go
+++ b/libgo/go/go/doc/reader.go
@@ -104,6 +104,8 @@ func baseTypeName(x ast.Expr) (name string, imported bool) {
 			// assume type is imported
 			return t.Sel.Name, true
 		}
+	case *ast.ParenExpr:
+		return baseTypeName(t.X)
 	case *ast.StarExpr:
 		return baseTypeName(t.X)
 	}
@@ -389,27 +391,33 @@ func (r *reader) readFunc(fun *ast.FuncDecl) {
 		return
 	}
 
-	// associate factory functions with the first visible result type, if any
+	// Associate factory functions with the first visible result type, if that
+	// is the only type returned.
 	if fun.Type.Results.NumFields() >= 1 {
-		res := fun.Type.Results.List[0]
-		if len(res.Names) <= 1 {
+		var typ *namedType // type to associate the function with
+		numResultTypes := 0
+		for _, res := range fun.Type.Results.List {
 			// exactly one (named or anonymous) result associated
 			// with the first type in result signature (there may
 			// be more than one result)
 			factoryType := res.Type
-			if t, ok := factoryType.(*ast.ArrayType); ok && t.Len == nil {
-				// We consider functions that return slices of type T (or
-				// pointers to T) as factory functions of T.
+			if t, ok := factoryType.(*ast.ArrayType); ok {
+				// We consider functions that return slices or arrays of type
+				// T (or pointers to T) as factory functions of T.
 				factoryType = t.Elt
 			}
 			if n, imp := baseTypeName(factoryType); !imp && r.isVisible(n) {
-				if typ := r.lookupType(n); typ != nil {
-					// associate function with typ
-					typ.funcs.set(fun)
-					return
+				if t := r.lookupType(n); t != nil {
+					typ = t
+					numResultTypes++
 				}
 			}
 		}
+		// If there is exactly one result type, associate the function with that type.
+		if numResultTypes == 1 {
+			typ.funcs.set(fun)
+			return
+		}
 	}
 
 	// just an ordinary function
diff --git a/libgo/go/go/doc/testdata/g.0.golden b/libgo/go/go/doc/testdata/g.0.golden
new file mode 100644
index 00000000000..487cf06ae53
--- /dev/null
+++ b/libgo/go/go/doc/testdata/g.0.golden
@@ -0,0 +1,32 @@
+// The package g is a go/doc test for mixed exported/unexported ...
+PACKAGE g
+
+IMPORTPATH
+	testdata/g
+
+FILENAMES
+	testdata/g.go
+
+CONSTANTS
+	// 
+	const (
+		A, _	= iota, iota
+		_, D
+		E, _
+		G, H
+	)
+
+
+VARIABLES
+	// 
+	var (
+		_, C2, _	= 1, 2, 3
+		C4, _, C6	= 4, 5, 6
+		_, C8, _	= 7, 8, 9
+	)
+
+	// 
+	var (
+		_, X = f()
+	)
+
diff --git a/libgo/go/go/doc/testdata/g.1.golden b/libgo/go/go/doc/testdata/g.1.golden
new file mode 100644
index 00000000000..438441ac545
--- /dev/null
+++ b/libgo/go/go/doc/testdata/g.1.golden
@@ -0,0 +1,34 @@
+// The package g is a go/doc test for mixed exported/unexported ...
+PACKAGE g
+
+IMPORTPATH
+	testdata/g
+
+FILENAMES
+	testdata/g.go
+
+CONSTANTS
+	// 
+	const (
+		A, b	= iota, iota
+		c, D
+		E, f
+		G, H
+	)
+
+
+VARIABLES
+	// 
+	var (
+		c1, C2, c3	= 1, 2, 3
+		C4, c5, C6	= 4, 5, 6
+		c7, C8, c9	= 7, 8, 9
+		xx, yy, zz	= 0, 0, 0	// all unexported and hidden
+	)
+
+	// 
+	var (
+		x, X	= f()
+		y, z	= f()
+	)
+
diff --git a/libgo/go/go/doc/testdata/g.2.golden b/libgo/go/go/doc/testdata/g.2.golden
new file mode 100644
index 00000000000..487cf06ae53
--- /dev/null
+++ b/libgo/go/go/doc/testdata/g.2.golden
@@ -0,0 +1,32 @@
+// The package g is a go/doc test for mixed exported/unexported ...
+PACKAGE g
+
+IMPORTPATH
+	testdata/g
+
+FILENAMES
+	testdata/g.go
+
+CONSTANTS
+	// 
+	const (
+		A, _	= iota, iota
+		_, D
+		E, _
+		G, H
+	)
+
+
+VARIABLES
+	// 
+	var (
+		_, C2, _	= 1, 2, 3
+		C4, _, C6	= 4, 5, 6
+		_, C8, _	= 7, 8, 9
+	)
+
+	// 
+	var (
+		_, X = f()
+	)
+
diff --git a/libgo/go/go/doc/testdata/g.go b/libgo/go/go/doc/testdata/g.go
new file mode 100644
index 00000000000..ceeb4174435
--- /dev/null
+++ b/libgo/go/go/doc/testdata/g.go
@@ -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.
+
+// The package g is a go/doc test for mixed exported/unexported values.
+package g
+
+const (
+	A, b = iota, iota
+	c, D
+	E, f
+	G, H
+)
+
+var (
+	c1, C2, c3 = 1, 2, 3
+	C4, c5, C6 = 4, 5, 6
+	c7, C8, c9 = 7, 8, 9
+	xx, yy, zz = 0, 0, 0 // all unexported and hidden
+)
+
+var (
+	x, X = f()
+	y, z = f()
+)
diff --git a/libgo/go/go/doc/testdata/issue12839.0.golden b/libgo/go/go/doc/testdata/issue12839.0.golden
new file mode 100644
index 00000000000..76c28555602
--- /dev/null
+++ b/libgo/go/go/doc/testdata/issue12839.0.golden
@@ -0,0 +1,33 @@
+// Package issue12839 is a go/doc test to test association of a ...
+PACKAGE issue12839
+
+IMPORTPATH
+	testdata/issue12839
+
+IMPORTS
+	p
+
+FILENAMES
+	testdata/issue12839.go
+
+FUNCTIONS
+	// F1 should not be associated with T1 
+	func F1() (*T1, *T2)
+
+	// F4 should not be associated with a type (same as F1) 
+	func F4() (a T1, b T2)
+
+
+TYPES
+	// 
+	type T1 struct{}
+
+	// F2 should be associated with T1 
+	func F2() (a, b, c T1)
+
+	// F3 should be associated with T1 because b.T3 is from a ...
+	func F3() (a T1, b p.T3)
+
+	// 
+	type T2 struct{}
+
diff --git a/libgo/go/go/doc/testdata/issue12839.1.golden b/libgo/go/go/doc/testdata/issue12839.1.golden
new file mode 100644
index 00000000000..b0a327ffd64
--- /dev/null
+++ b/libgo/go/go/doc/testdata/issue12839.1.golden
@@ -0,0 +1,36 @@
+// Package issue12839 is a go/doc test to test association of a ...
+PACKAGE issue12839
+
+IMPORTPATH
+	testdata/issue12839
+
+IMPORTS
+	p
+
+FILENAMES
+	testdata/issue12839.go
+
+FUNCTIONS
+	// F1 should not be associated with T1 
+	func F1() (*T1, *T2)
+
+	// F4 should not be associated with a type (same as F1) 
+	func F4() (a T1, b T2)
+
+
+TYPES
+	// 
+	type T1 struct{}
+
+	// F2 should be associated with T1 
+	func F2() (a, b, c T1)
+
+	// F3 should be associated with T1 because b.T3 is from a ...
+	func F3() (a T1, b p.T3)
+
+	// 
+	func (t T1) hello() string
+
+	// 
+	type T2 struct{}
+
diff --git a/libgo/go/go/doc/testdata/issue12839.2.golden b/libgo/go/go/doc/testdata/issue12839.2.golden
new file mode 100644
index 00000000000..76c28555602
--- /dev/null
+++ b/libgo/go/go/doc/testdata/issue12839.2.golden
@@ -0,0 +1,33 @@
+// Package issue12839 is a go/doc test to test association of a ...
+PACKAGE issue12839
+
+IMPORTPATH
+	testdata/issue12839
+
+IMPORTS
+	p
+
+FILENAMES
+	testdata/issue12839.go
+
+FUNCTIONS
+	// F1 should not be associated with T1 
+	func F1() (*T1, *T2)
+
+	// F4 should not be associated with a type (same as F1) 
+	func F4() (a T1, b T2)
+
+
+TYPES
+	// 
+	type T1 struct{}
+
+	// F2 should be associated with T1 
+	func F2() (a, b, c T1)
+
+	// F3 should be associated with T1 because b.T3 is from a ...
+	func F3() (a T1, b p.T3)
+
+	// 
+	type T2 struct{}
+
diff --git a/libgo/go/go/doc/testdata/issue12839.go b/libgo/go/go/doc/testdata/issue12839.go
new file mode 100644
index 00000000000..500d49511b5
--- /dev/null
+++ b/libgo/go/go/doc/testdata/issue12839.go
@@ -0,0 +1,38 @@
+// 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 issue12839 is a go/doc test to test association of a function
+// that returns multiple types.
+// See golang.org/issue/12839.
+package issue12839
+
+import "p"
+
+type T1 struct{}
+
+type T2 struct{}
+
+func (t T1) hello() string {
+	return "hello"
+}
+
+// F1 should not be associated with T1
+func F1() (*T1, *T2) {
+	return &T1{}, &T2{}
+}
+
+// F2 should be associated with T1
+func F2() (a, b, c T1) {
+	return T1{}, T1{}, T1{}
+}
+
+// F3 should be associated with T1 because b.T3 is from a different package
+func F3() (a T1, b p.T3) {
+	return T1{}, p.T3{}
+}
+
+// F4 should not be associated with a type (same as F1)
+func F4() (a T1, b T2) {
+	return T1{}, T2{}
+}
diff --git a/libgo/go/go/doc/testdata/issue18063.2.golden b/libgo/go/go/doc/testdata/issue22856.0.golden
similarity index 73%
rename from libgo/go/go/doc/testdata/issue18063.2.golden
rename to libgo/go/go/doc/testdata/issue22856.0.golden
index 0afbc169c2c..a88f43f4bd7 100644
--- a/libgo/go/go/doc/testdata/issue18063.2.golden
+++ b/libgo/go/go/doc/testdata/issue22856.0.golden
@@ -1,19 +1,13 @@
 // 
-PACKAGE issue18063
+PACKAGE issue22856
 
 IMPORTPATH
-	testdata/issue18063
+	testdata/issue22856
 
 FILENAMES
-	testdata/issue18063.go
+	testdata/issue22856.go
 
 FUNCTIONS
-	// NewArray is not a factory function because arrays of type T are ...
-	func NewArray() [1]T
-
-	// NewPointerArray is not a factory function because arrays of ...
-	func NewPointerArray() [1]*T
-
 	// NewPointerSliceOfSlice is not a factory function because slices ...
 	func NewPointerSliceOfSlice() [][]*T
 
@@ -31,9 +25,15 @@ TYPES
 	// 
 	func New() T
 
+	// 
+	func NewArray() [1]T
+
 	// 
 	func NewPointer() *T
 
+	// 
+	func NewPointerArray() [1]*T
+
 	// 
 	func NewPointerOfPointer() **T
 
diff --git a/libgo/go/go/doc/testdata/issue18063.1.golden b/libgo/go/go/doc/testdata/issue22856.1.golden
similarity index 73%
rename from libgo/go/go/doc/testdata/issue18063.1.golden
rename to libgo/go/go/doc/testdata/issue22856.1.golden
index 0afbc169c2c..a88f43f4bd7 100644
--- a/libgo/go/go/doc/testdata/issue18063.1.golden
+++ b/libgo/go/go/doc/testdata/issue22856.1.golden
@@ -1,19 +1,13 @@
 // 
-PACKAGE issue18063
+PACKAGE issue22856
 
 IMPORTPATH
-	testdata/issue18063
+	testdata/issue22856
 
 FILENAMES
-	testdata/issue18063.go
+	testdata/issue22856.go
 
 FUNCTIONS
-	// NewArray is not a factory function because arrays of type T are ...
-	func NewArray() [1]T
-
-	// NewPointerArray is not a factory function because arrays of ...
-	func NewPointerArray() [1]*T
-
 	// NewPointerSliceOfSlice is not a factory function because slices ...
 	func NewPointerSliceOfSlice() [][]*T
 
@@ -31,9 +25,15 @@ TYPES
 	// 
 	func New() T
 
+	// 
+	func NewArray() [1]T
+
 	// 
 	func NewPointer() *T
 
+	// 
+	func NewPointerArray() [1]*T
+
 	// 
 	func NewPointerOfPointer() **T
 
diff --git a/libgo/go/go/doc/testdata/issue18063.0.golden b/libgo/go/go/doc/testdata/issue22856.2.golden
similarity index 73%
rename from libgo/go/go/doc/testdata/issue18063.0.golden
rename to libgo/go/go/doc/testdata/issue22856.2.golden
index 0afbc169c2c..a88f43f4bd7 100644
--- a/libgo/go/go/doc/testdata/issue18063.0.golden
+++ b/libgo/go/go/doc/testdata/issue22856.2.golden
@@ -1,19 +1,13 @@
 // 
-PACKAGE issue18063
+PACKAGE issue22856
 
 IMPORTPATH
-	testdata/issue18063
+	testdata/issue22856
 
 FILENAMES
-	testdata/issue18063.go
+	testdata/issue22856.go
 
 FUNCTIONS
-	// NewArray is not a factory function because arrays of type T are ...
-	func NewArray() [1]T
-
-	// NewPointerArray is not a factory function because arrays of ...
-	func NewPointerArray() [1]*T
-
 	// NewPointerSliceOfSlice is not a factory function because slices ...
 	func NewPointerSliceOfSlice() [][]*T
 
@@ -31,9 +25,15 @@ TYPES
 	// 
 	func New() T
 
+	// 
+	func NewArray() [1]T
+
 	// 
 	func NewPointer() *T
 
+	// 
+	func NewPointerArray() [1]*T
+
 	// 
 	func NewPointerOfPointer() **T
 
diff --git a/libgo/go/go/doc/testdata/issue18063.go b/libgo/go/go/doc/testdata/issue22856.go
similarity index 74%
rename from libgo/go/go/doc/testdata/issue18063.go
rename to libgo/go/go/doc/testdata/issue22856.go
index 1193af51e7c..f4569981aaa 100644
--- a/libgo/go/go/doc/testdata/issue18063.go
+++ b/libgo/go/go/doc/testdata/issue22856.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 issue18063
+package issue22856
 
 type T struct{}
 
@@ -11,14 +11,8 @@ func NewPointer() *T           { return &T{} }
 func NewPointerSlice() []*T    { return []*T{&T{}} }
 func NewSlice() []T            { return []T{T{}} }
 func NewPointerOfPointer() **T { x := &T{}; return &x }
-
-// NewArray is not a factory function because arrays of type T are not
-// factory functions of type T.
-func NewArray() [1]T { return [1]T{T{}} }
-
-// NewPointerArray is not a factory function because arrays of type *T are not
-// factory functions of type T.
-func NewPointerArray() [1]*T { return [1]*T{&T{}} }
+func NewArray() [1]T           { return [1]T{T{}} }
+func NewPointerArray() [1]*T   { return [1]*T{&T{}} }
 
 // NewSliceOfSlice is not a factory function because slices of a slice of
 // type *T are not factory functions of type T.
diff --git a/libgo/go/go/format/example_test.go b/libgo/go/go/format/example_test.go
new file mode 100644
index 00000000000..3d72997fa20
--- /dev/null
+++ b/libgo/go/go/format/example_test.go
@@ -0,0 +1,41 @@
+// 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 gccgo_examples
+
+package format_test
+
+import (
+	"bytes"
+	"fmt"
+	"go/format"
+	"go/parser"
+	"go/token"
+	"log"
+)
+
+func ExampleNode() {
+	const expr = "(6+2*3)/4"
+
+	// parser.ParseExpr parses the argument and returns the
+	// corresponding ast.Node.
+	node, err := parser.ParseExpr(expr)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	// Create a FileSet for node. Since the node does not come
+	// from a real source file, fset will be empty.
+	fset := token.NewFileSet()
+
+	var buf bytes.Buffer
+	err = format.Node(&buf, fset, node)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Println(buf.String())
+
+	// Output: (6 + 2*3) / 4
+}
diff --git a/libgo/go/go/format/format.go b/libgo/go/go/format/format.go
index cad5958e5c5..9aa28fc63b2 100644
--- a/libgo/go/go/format/format.go
+++ b/libgo/go/go/format/format.go
@@ -3,6 +3,15 @@
 // license that can be found in the LICENSE file.
 
 // Package format implements standard formatting of Go source.
+//
+// Note that formatting of Go source code changes over time, so tools relying on
+// consistent formatting should execute a specific version of the gofmt binary
+// instead of using this package. That way, the formatting will be stable, and
+// the tools won't need to be recompiled each time gofmt changes.
+//
+// For example, pre-submit checks that use this package directly would behave
+// differently depending on what Go version each developer uses, causing the
+// check to be inherently fragile.
 package format
 
 import (
@@ -79,10 +88,6 @@ func Node(dst io.Writer, fset *token.FileSet, node interface{}) error {
 // space as src), and the result is indented by the same amount as the first
 // line of src containing code. Imports are not sorted for partial source files.
 //
-// Caution: Tools relying on consistent formatting based on the installed
-// version of gofmt (for instance, such as for presubmit checks) should
-// execute that gofmt binary instead of calling Source.
-//
 func Source(src []byte) ([]byte, error) {
 	fset := token.NewFileSet()
 	file, sourceAdj, indentAdj, err := parse(fset, "", src, true)
diff --git a/libgo/go/go/format/format_test.go b/libgo/go/go/format/format_test.go
index 72b8d5aeeb5..b5817a5dd18 100644
--- a/libgo/go/go/format/format_test.go
+++ b/libgo/go/go/format/format_test.go
@@ -6,11 +6,9 @@ package format
 
 import (
 	"bytes"
-	"fmt"
 	"go/parser"
 	"go/token"
 	"io/ioutil"
-	"log"
 	"strings"
 	"testing"
 )
@@ -145,28 +143,3 @@ func TestPartial(t *testing.T) {
 		}
 	}
 }
-
-func ExampleNode() {
-	const expr = "(6+2*3)/4"
-
-	// parser.ParseExpr parses the argument and returns the
-	// corresponding ast.Node.
-	node, err := parser.ParseExpr(expr)
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	// Create a FileSet for node. Since the node does not come
-	// from a real source file, fset will be empty.
-	fset := token.NewFileSet()
-
-	var buf bytes.Buffer
-	err = Node(&buf, fset, node)
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	fmt.Println(buf.String())
-
-	// Output: (6 + 2*3) / 4
-}
diff --git a/libgo/go/go/internal/gccgoimporter/ar.go b/libgo/go/go/internal/gccgoimporter/ar.go
new file mode 100644
index 00000000000..ebd08b8f359
--- /dev/null
+++ b/libgo/go/go/internal/gccgoimporter/ar.go
@@ -0,0 +1,148 @@
+// 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 gccgoimporter
+
+import (
+	"bytes"
+	"debug/elf"
+	"errors"
+	"fmt"
+	"io"
+	"strconv"
+	"strings"
+)
+
+// Magic strings for different archive file formats.
+const (
+	armag  = "!\n"
+	armagt = "!\n"
+	armagb = "\n"
+)
+
+// Offsets and sizes for fields in a standard archive header.
+const (
+	arNameOff  = 0
+	arNameSize = 16
+	arDateOff  = arNameOff + arNameSize
+	arDateSize = 12
+	arUIDOff   = arDateOff + arDateSize
+	arUIDSize  = 6
+	arGIDOff   = arUIDOff + arUIDSize
+	arGIDSize  = 6
+	arModeOff  = arGIDOff + arGIDSize
+	arModeSize = 8
+	arSizeOff  = arModeOff + arModeSize
+	arSizeSize = 10
+	arFmagOff  = arSizeOff + arSizeSize
+	arFmagSize = 2
+
+	arHdrSize = arFmagOff + arFmagSize
+)
+
+// The contents of the fmag field of a standard archive header.
+const arfmag = "`\n"
+
+// arExportData takes an archive file and returns a ReadSeeker for the
+// export data in that file. This assumes that there is only one
+// object in the archive containing export data, which is not quite
+// what gccgo does; gccgo concatenates together all the export data
+// for all the objects in the file.  In practice that case does not arise.
+func arExportData(archive io.ReadSeeker) (io.ReadSeeker, error) {
+	if _, err := archive.Seek(0, io.SeekStart); err != nil {
+		return nil, err
+	}
+
+	var buf [len(armag)]byte
+	if _, err := archive.Read(buf[:]); err != nil {
+		return nil, err
+	}
+
+	switch string(buf[:]) {
+	case armag:
+		return standardArExportData(archive)
+	case armagt:
+		return nil, errors.New("unsupported thin archive")
+	case armagb:
+		return nil, errors.New("unsupported AIX big archive")
+	default:
+		return nil, fmt.Errorf("unrecognized archive file format %q", buf[:])
+	}
+}
+
+// standardArExportData returns export data form a standard archive.
+func standardArExportData(archive io.ReadSeeker) (io.ReadSeeker, error) {
+	off := int64(len(armag))
+	for {
+		var hdrBuf [arHdrSize]byte
+		if _, err := archive.Read(hdrBuf[:]); err != nil {
+			return nil, err
+		}
+		off += arHdrSize
+
+		if bytes.Compare(hdrBuf[arFmagOff:arFmagOff+arFmagSize], []byte(arfmag)) != 0 {
+			return nil, fmt.Errorf("archive header format header (%q)", hdrBuf[:])
+		}
+
+		size, err := strconv.ParseInt(strings.TrimSpace(string(hdrBuf[arSizeOff:arSizeOff+arSizeSize])), 10, 64)
+		if err != nil {
+			return nil, fmt.Errorf("error parsing size in archive header (%q): %v", hdrBuf[:], err)
+		}
+
+		fn := hdrBuf[arNameOff : arNameOff+arNameSize]
+		if fn[0] == '/' && (fn[1] == ' ' || fn[1] == '/' || bytes.Compare(fn[:8], []byte("/SYM64/ ")) == 0) {
+			// Archive symbol table or extended name table,
+			// which we don't care about.
+		} else {
+			archiveAt := readerAtFromSeeker(archive)
+			ret, err := elfFromAr(io.NewSectionReader(archiveAt, off, size))
+			if ret != nil || err != nil {
+				return ret, err
+			}
+		}
+
+		if size&1 != 0 {
+			size++
+		}
+		off += size
+		if _, err := archive.Seek(off, io.SeekStart); err != nil {
+			return nil, err
+		}
+	}
+}
+
+// elfFromAr tries to get export data from an archive member as an ELF file.
+// If there is no export data, this returns nil, nil.
+func elfFromAr(member *io.SectionReader) (io.ReadSeeker, error) {
+	ef, err := elf.NewFile(member)
+	if err != nil {
+		return nil, err
+	}
+	sec := ef.Section(".go_export")
+	if sec == nil {
+		return nil, nil
+	}
+	return sec.Open(), nil
+}
+
+// readerAtFromSeeker turns an io.ReadSeeker into an io.ReaderAt.
+// This is only safe because there won't be any concurrent seeks
+// while this code is executing.
+func readerAtFromSeeker(rs io.ReadSeeker) io.ReaderAt {
+	if ret, ok := rs.(io.ReaderAt); ok {
+		return ret
+	}
+	return seekerReadAt{rs}
+}
+
+type seekerReadAt struct {
+	seeker io.ReadSeeker
+}
+
+func (sra seekerReadAt) ReadAt(p []byte, off int64) (int, error) {
+	if _, err := sra.seeker.Seek(off, io.SeekStart); err != nil {
+		return 0, err
+	}
+	return sra.seeker.Read(p)
+}
diff --git a/libgo/go/go/internal/gccgoimporter/importer.go b/libgo/go/go/internal/gccgoimporter/importer.go
index ddaed405c18..7bc2afc4d78 100644
--- a/libgo/go/go/internal/gccgoimporter/importer.go
+++ b/libgo/go/go/internal/gccgoimporter/importer.go
@@ -13,9 +13,7 @@ import (
 	"go/types"
 	"io"
 	"os"
-	"os/exec"
 	"path/filepath"
-	"runtime"
 	"strings"
 )
 
@@ -100,26 +98,9 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e
 		reader = f
 		return
 
-	case archiveMagic, aixbigafMagic:
-		// TODO(pcc): Read the archive directly instead of using "ar".
-		f.Close()
-		closer = nil
-		var cmd *exec.Cmd
-
-		if runtime.GOOS == "aix" && runtime.GOARCH == "ppc64" {
-			// AIX puts both 32-bit and 64-bit objects in the same archive.
-			// Tell the AIX "ar" command to only care about 64-bit objects.
-			cmd = exec.Command("ar", "-X64", "p", fpath)
-		} else {
-			cmd = exec.Command("ar", "p", fpath)
-		}
-		var out []byte
-		out, err = cmd.Output()
-		if err != nil {
-			return
-		}
-
-		objreader = bytes.NewReader(out)
+	case archiveMagic:
+		reader, err = arExportData(f)
+		return
 
 	default:
 		objreader = f
@@ -171,26 +152,29 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo
 
 		var reader io.ReadSeeker
 		var fpath string
+		var rc io.ReadCloser
 		if lookup != nil {
 			if p := imports[pkgpath]; p != nil && p.Complete() {
 				return p, nil
 			}
-			rc, err := lookup(pkgpath)
-			if err == nil && rc != nil {
-				defer rc.Close()
-				rs, ok := rc.(io.ReadSeeker)
-				if !ok {
-					return nil, fmt.Errorf("gccgo importer requires lookup to return an io.ReadSeeker, have %T", rc)
-				}
-				reader = rs
-				fpath = ""
-				// Take name from Name method (like on os.File) if present.
-				if n, ok := rc.(interface{ Name() string }); ok {
-					fpath = n.Name()
-				}
+			rc, err = lookup(pkgpath)
+			if err != nil {
+				return nil, err
 			}
 		}
-		if reader == nil {
+		if rc != nil {
+			defer rc.Close()
+			rs, ok := rc.(io.ReadSeeker)
+			if !ok {
+				return nil, fmt.Errorf("gccgo importer requires lookup to return an io.ReadSeeker, have %T", rc)
+			}
+			reader = rs
+			fpath = ""
+			// Take name from Name method (like on os.File) if present.
+			if n, ok := rc.(interface{ Name() string }); ok {
+				fpath = n.Name()
+			}
+		} else {
 			fpath, err = findExportFile(searchpaths, pkgpath)
 			if err != nil {
 				return nil, err
@@ -206,17 +190,24 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo
 			reader = r
 		}
 
-		var magic [4]byte
-		_, err = reader.Read(magic[:])
-		if err != nil {
-			return
-		}
-		_, err = reader.Seek(0, io.SeekStart)
+		var magics string
+		magics, err = readMagic(reader)
 		if err != nil {
 			return
 		}
 
-		switch string(magic[:]) {
+		if magics == archiveMagic {
+			reader, err = arExportData(reader)
+			if err != nil {
+				return
+			}
+			magics, err = readMagic(reader)
+			if err != nil {
+				return
+			}
+		}
+
+		switch magics {
 		case gccgov1Magic, gccgov2Magic:
 			var p parser
 			p.init(fpath, reader, imports)
@@ -247,9 +238,22 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo
 		// 	}
 
 		default:
-			err = fmt.Errorf("unrecognized magic string: %q", string(magic[:]))
+			err = fmt.Errorf("unrecognized magic string: %q", magics)
 		}
 
 		return
 	}
 }
+
+// readMagic reads the four bytes at the start of a ReadSeeker and
+// returns them as a string.
+func readMagic(reader io.ReadSeeker) (string, error) {
+	var magic [4]byte
+	if _, err := reader.Read(magic[:]); err != nil {
+		return "", err
+	}
+	if _, err := reader.Seek(0, io.SeekStart); err != nil {
+		return "", err
+	}
+	return string(magic[:]), nil
+}
diff --git a/libgo/go/go/internal/gccgoimporter/importer_test.go b/libgo/go/go/internal/gccgoimporter/importer_test.go
index 01ab47a4451..5a699687bd4 100644
--- a/libgo/go/go/internal/gccgoimporter/importer_test.go
+++ b/libgo/go/go/internal/gccgoimporter/importer_test.go
@@ -101,6 +101,7 @@ var importerTests = [...]importerTest{
 	{pkgpath: "unicode", name: "IsUpper", want: "func IsUpper(r rune) bool"},
 	{pkgpath: "unicode", name: "MaxRune", want: "const MaxRune untyped rune", wantval: "1114111"},
 	{pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}},
+	{pkgpath: "importsar", name: "Hello", want: "var Hello string"},
 	{pkgpath: "alias", name: "IntAlias2", want: "type IntAlias2 = Int"},
 	{pkgpath: "escapeinfo", name: "NewT", want: "func NewT(data []byte) *T"},
 }
diff --git a/libgo/go/go/internal/gccgoimporter/parser.go b/libgo/go/go/internal/gccgoimporter/parser.go
index 4b3d899efd1..9f8c19b6388 100644
--- a/libgo/go/go/internal/gccgoimporter/parser.go
+++ b/libgo/go/go/internal/gccgoimporter/parser.go
@@ -585,13 +585,13 @@ func (p *parser) parseInterfaceType(pkg *types.Package) types.Type {
 	p.expectKeyword("interface")
 
 	var methods []*types.Func
-	var typs []*types.Named
+	var embeddeds []types.Type
 
 	p.expect('{')
 	for p.tok != '}' && p.tok != scanner.EOF {
 		if p.tok == '?' {
 			p.next()
-			typs = append(typs, p.parseType(pkg).(*types.Named))
+			embeddeds = append(embeddeds, p.parseType(pkg))
 		} else {
 			method := p.parseFunc(pkg)
 			methods = append(methods, method)
@@ -600,7 +600,7 @@ func (p *parser) parseInterfaceType(pkg *types.Package) types.Type {
 	}
 	p.expect('}')
 
-	return types.NewInterface(methods, typs)
+	return types.NewInterfaceType(methods, embeddeds)
 }
 
 // PointerType = "*" ("any" | Type) .
@@ -906,10 +906,3 @@ func (p *parser) parsePackage() *types.Package {
 	p.pkg.MarkComplete()
 	return p.pkg
 }
-
-// InitData = { InitDataDirective } .
-func (p *parser) parseInitData() {
-	for p.tok != scanner.EOF {
-		p.parseInitDataDirective()
-	}
-}
diff --git a/libgo/go/go/internal/gcimporter/bimport.go b/libgo/go/go/internal/gcimporter/bimport.go
index 23c1d2f76a9..4e3023b906e 100644
--- a/libgo/go/go/internal/gcimporter/bimport.go
+++ b/libgo/go/go/internal/gcimporter/bimport.go
@@ -37,8 +37,7 @@ type importer struct {
 	posInfoFormat bool
 	prevFile      string
 	prevLine      int
-	fset          *token.FileSet
-	files         map[string]*token.File
+	fake          fakeFileSet
 
 	// debugging support
 	debugFormat bool
@@ -51,12 +50,16 @@ type importer struct {
 // compromised, an error is returned.
 func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
 	// catch panics and return them as errors
+	const currentVersion = 6
+	version := -1 // unknown version
 	defer func() {
 		if e := recover(); e != nil {
-			// The package (filename) causing the problem is added to this
-			// error by a wrapper in the caller (Import in gcimporter.go).
 			// Return a (possibly nil or incomplete) package unchanged (see #16088).
-			err = fmt.Errorf("cannot import, possibly version skew (%v) - reinstall package", e)
+			if version > currentVersion {
+				err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
+			} else {
+				err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
+			}
 		}
 	}()
 
@@ -64,11 +67,13 @@ func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []
 		imports:    imports,
 		data:       data,
 		importpath: path,
-		version:    -1,           // unknown version
+		version:    version,
 		strList:    []string{""}, // empty string is mapped to 0
 		pathList:   []string{""}, // empty string is mapped to 0
-		fset:       fset,
-		files:      make(map[string]*token.File),
+		fake: fakeFileSet{
+			fset:  fset,
+			files: make(map[string]*token.File),
+		},
 	}
 
 	// read version info
@@ -87,7 +92,7 @@ func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []
 		p.posInfoFormat = p.int() != 0
 		versionstr = p.string()
 		if versionstr == "v1" {
-			p.version = 0
+			version = 0
 		}
 	} else {
 		// Go1.8 extensible encoding
@@ -95,24 +100,25 @@ func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []
 		versionstr = p.rawStringln(b)
 		if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" {
 			if v, err := strconv.Atoi(s[1]); err == nil && v > 0 {
-				p.version = v
+				version = v
 			}
 		}
 	}
+	p.version = version
 
 	// read version specific flags - extend as necessary
 	switch p.version {
-	// case 6:
+	// case currentVersion:
 	// 	...
 	//	fallthrough
-	case 5, 4, 3, 2, 1:
+	case currentVersion, 5, 4, 3, 2, 1:
 		p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
 		p.trackAllTypes = p.int() != 0
 		p.posInfoFormat = p.int() != 0
 	case 0:
 		// Go1.7 encoding format - nothing to do here
 	default:
-		errorf("unknown export format version %d (%q)", p.version, versionstr)
+		errorf("unknown bexport format version %d (%q)", p.version, versionstr)
 	}
 
 	// --- generic export data ---
@@ -182,6 +188,9 @@ func (p *importer) pkg() *types.Package {
 	} else {
 		path = p.string()
 	}
+	if p.version >= 6 {
+		p.int() // package height; unused by go/types
+	}
 
 	// we should never see an empty package name
 	if name == "" {
@@ -257,7 +266,7 @@ func (p *importer) obj(tag int) {
 	case constTag:
 		pos := p.pos()
 		pkg, name := p.qualifiedName()
-		typ := p.typ(nil)
+		typ := p.typ(nil, nil)
 		val := p.value()
 		p.declare(types.NewConst(pos, pkg, name, typ, val))
 
@@ -265,16 +274,16 @@ func (p *importer) obj(tag int) {
 		// TODO(gri) verify type alias hookup is correct
 		pos := p.pos()
 		pkg, name := p.qualifiedName()
-		typ := p.typ(nil)
+		typ := p.typ(nil, nil)
 		p.declare(types.NewTypeName(pos, pkg, name, typ))
 
 	case typeTag:
-		p.typ(nil)
+		p.typ(nil, nil)
 
 	case varTag:
 		pos := p.pos()
 		pkg, name := p.qualifiedName()
-		typ := p.typ(nil)
+		typ := p.typ(nil, nil)
 		p.declare(types.NewVar(pos, pkg, name, typ))
 
 	case funcTag:
@@ -321,15 +330,23 @@ func (p *importer) pos() token.Pos {
 	p.prevFile = file
 	p.prevLine = line
 
-	// Synthesize a token.Pos
+	return p.fake.pos(file, line)
+}
 
+// Synthesize a token.Pos
+type fakeFileSet struct {
+	fset  *token.FileSet
+	files map[string]*token.File
+}
+
+func (s *fakeFileSet) pos(file string, line int) token.Pos {
 	// Since we don't know the set of needed file positions, we
 	// reserve maxlines positions per file.
 	const maxlines = 64 * 1024
-	f := p.files[file]
+	f := s.files[file]
 	if f == nil {
-		f = p.fset.AddFile(file, -1, maxlines)
-		p.files[file] = f
+		f = s.fset.AddFile(file, -1, maxlines)
+		s.files[file] = f
 		// Allocate the fake linebreak indices on first use.
 		// TODO(adonovan): opt: save ~512KB using a more complex scheme?
 		fakeLinesOnce.Do(func() {
@@ -379,7 +396,11 @@ func (t *dddSlice) String() string         { return "..." + t.elem.String() }
 // the package currently imported. The parent package is needed for
 // exported struct fields and interface methods which don't contain
 // explicit package information in the export data.
-func (p *importer) typ(parent *types.Package) types.Type {
+//
+// A non-nil tname is used as the "owner" of the result type; i.e.,
+// the result type is the underlying type of tname. tname is used
+// to give interface methods a named receiver type where possible.
+func (p *importer) typ(parent *types.Package, tname *types.Named) types.Type {
 	// if the type was seen before, i is its index (>= 0)
 	i := p.tagOrIndex()
 	if i >= 0 {
@@ -409,15 +430,15 @@ func (p *importer) typ(parent *types.Package) types.Type {
 		t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
 
 		// but record the existing type, if any
-		t := obj.Type().(*types.Named)
-		p.record(t)
+		tname := obj.Type().(*types.Named) // tname is either t0 or the existing type
+		p.record(tname)
 
 		// read underlying type
-		t0.SetUnderlying(p.typ(parent))
+		t0.SetUnderlying(p.typ(parent, t0))
 
 		// interfaces don't have associated methods
 		if types.IsInterface(t0) {
-			return t
+			return tname
 		}
 
 		// read associated methods
@@ -438,7 +459,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
 			t0.AddMethod(types.NewFunc(pos, parent, name, sig))
 		}
 
-		return t
+		return tname
 
 	case arrayTag:
 		t := new(types.Array)
@@ -447,7 +468,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
 		}
 
 		n := p.int64()
-		*t = *types.NewArray(p.typ(parent), n)
+		*t = *types.NewArray(p.typ(parent, nil), n)
 		return t
 
 	case sliceTag:
@@ -456,7 +477,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
 			p.record(t)
 		}
 
-		*t = *types.NewSlice(p.typ(parent))
+		*t = *types.NewSlice(p.typ(parent, nil))
 		return t
 
 	case dddTag:
@@ -465,7 +486,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
 			p.record(t)
 		}
 
-		t.elem = p.typ(parent)
+		t.elem = p.typ(parent, nil)
 		return t
 
 	case structTag:
@@ -483,7 +504,7 @@ func (p *importer) typ(parent *types.Package) types.Type {
 			p.record(t)
 		}
 
-		*t = *types.NewPointer(p.typ(parent))
+		*t = *types.NewPointer(p.typ(parent, nil))
 		return t
 
 	case signatureTag:
@@ -502,18 +523,20 @@ func (p *importer) typ(parent *types.Package) types.Type {
 		// cannot expect the interface type to appear in a cycle, as any
 		// such cycle must contain a named type which would have been
 		// first defined earlier.
+		// TODO(gri) Is this still true now that we have type aliases?
+		// See issue #23225.
 		n := len(p.typList)
 		if p.trackAllTypes {
 			p.record(nil)
 		}
 
-		var embeddeds []*types.Named
+		var embeddeds []types.Type
 		for n := p.int(); n > 0; n-- {
 			p.pos()
-			embeddeds = append(embeddeds, p.typ(parent).(*types.Named))
+			embeddeds = append(embeddeds, p.typ(parent, nil))
 		}
 
-		t := types.NewInterface(p.methodList(parent), embeddeds)
+		t := types.NewInterfaceType(p.methodList(parent, tname), embeddeds)
 		p.interfaceList = append(p.interfaceList, t)
 		if p.trackAllTypes {
 			p.typList[n] = t
@@ -526,8 +549,8 @@ func (p *importer) typ(parent *types.Package) types.Type {
 			p.record(t)
 		}
 
-		key := p.typ(parent)
-		val := p.typ(parent)
+		key := p.typ(parent, nil)
+		val := p.typ(parent, nil)
 		*t = *types.NewMap(key, val)
 		return t
 
@@ -537,19 +560,8 @@ func (p *importer) typ(parent *types.Package) types.Type {
 			p.record(t)
 		}
 
-		var dir types.ChanDir
-		// tag values must match the constants in cmd/compile/internal/gc/go.go
-		switch d := p.int(); d {
-		case 1 /* Crecv */ :
-			dir = types.RecvOnly
-		case 2 /* Csend */ :
-			dir = types.SendOnly
-		case 3 /* Cboth */ :
-			dir = types.SendRecv
-		default:
-			errorf("unexpected channel dir %d", d)
-		}
-		val := p.typ(parent)
+		dir := chanDir(p.int())
+		val := p.typ(parent, nil)
 		*t = *types.NewChan(dir, val)
 		return t
 
@@ -559,6 +571,21 @@ func (p *importer) typ(parent *types.Package) types.Type {
 	}
 }
 
+func chanDir(d int) types.ChanDir {
+	// tag values must match the constants in cmd/compile/internal/gc/go.go
+	switch d {
+	case 1 /* Crecv */ :
+		return types.RecvOnly
+	case 2 /* Csend */ :
+		return types.SendOnly
+	case 3 /* Cboth */ :
+		return types.SendRecv
+	default:
+		errorf("unexpected channel dir %d", d)
+		return 0
+	}
+}
+
 func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags []string) {
 	if n := p.int(); n > 0 {
 		fields = make([]*types.Var, n)
@@ -573,7 +600,7 @@ func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags [
 func (p *importer) field(parent *types.Package) (*types.Var, string) {
 	pos := p.pos()
 	pkg, name, alias := p.fieldName(parent)
-	typ := p.typ(parent)
+	typ := p.typ(parent, nil)
 	tag := p.string()
 
 	anonymous := false
@@ -597,22 +624,30 @@ func (p *importer) field(parent *types.Package) (*types.Var, string) {
 	return types.NewField(pos, pkg, name, typ, anonymous), tag
 }
 
-func (p *importer) methodList(parent *types.Package) (methods []*types.Func) {
+func (p *importer) methodList(parent *types.Package, baseType *types.Named) (methods []*types.Func) {
 	if n := p.int(); n > 0 {
 		methods = make([]*types.Func, n)
 		for i := range methods {
-			methods[i] = p.method(parent)
+			methods[i] = p.method(parent, baseType)
 		}
 	}
 	return
 }
 
-func (p *importer) method(parent *types.Package) *types.Func {
+func (p *importer) method(parent *types.Package, baseType *types.Named) *types.Func {
 	pos := p.pos()
 	pkg, name, _ := p.fieldName(parent)
+	// If we don't have a baseType, use a nil receiver.
+	// A receiver using the actual interface type (which
+	// we don't know yet) will be filled in when we call
+	// types.Interface.Complete.
+	var recv *types.Var
+	if baseType != nil {
+		recv = types.NewVar(token.NoPos, parent, "", baseType)
+	}
 	params, isddd := p.paramList()
 	result, _ := p.paramList()
-	sig := types.NewSignature(nil, params, result, isddd)
+	sig := types.NewSignature(recv, params, result, isddd)
 	return types.NewFunc(pos, pkg, name, sig)
 }
 
@@ -668,7 +703,7 @@ func (p *importer) paramList() (*types.Tuple, bool) {
 }
 
 func (p *importer) param(named bool) (*types.Var, bool) {
-	t := p.typ(nil)
+	t := p.typ(nil, nil)
 	td, isddd := t.(*dddSlice)
 	if isddd {
 		t = types.NewSlice(td.elem)
diff --git a/libgo/go/go/internal/gcimporter/gcimporter.go b/libgo/go/go/internal/gcimporter/gcimporter.go
index 2185f5b8910..d117f6fe4d3 100644
--- a/libgo/go/go/internal/gcimporter/gcimporter.go
+++ b/libgo/go/go/internal/gcimporter/gcimporter.go
@@ -133,9 +133,7 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
 		}()
 		rc = f
 	}
-	defer func() {
-		rc.Close()
-	}()
+	defer rc.Close()
 
 	var hdr string
 	buf := bufio.NewReader(rc)
@@ -146,16 +144,27 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
 	switch hdr {
 	case "$$\n":
 		err = fmt.Errorf("import %q: old export format no longer supported (recompile library)", path)
+
 	case "$$B\n":
 		var data []byte
 		data, err = ioutil.ReadAll(buf)
-		if err == nil {
-			// TODO(gri): allow clients of go/importer to provide a FileSet.
-			// Or, define a new standard go/types/gcexportdata package.
-			fset := token.NewFileSet()
-			_, pkg, err = BImportData(fset, packages, data, id)
-			return
+		if err != nil {
+			break
 		}
+
+		// TODO(gri): allow clients of go/importer to provide a FileSet.
+		// Or, define a new standard go/types/gcexportdata package.
+		fset := token.NewFileSet()
+
+		// 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)
+		} else {
+			_, pkg, err = BImportData(fset, packages, data, id)
+		}
+
 	default:
 		err = fmt.Errorf("unknown export data header: %q", hdr)
 	}
diff --git a/libgo/go/go/internal/gcimporter/gcimporter_test.go b/libgo/go/go/internal/gcimporter/gcimporter_test.go
index 56870a14121..d496f2e57d3 100644
--- a/libgo/go/go/internal/gcimporter/gcimporter_test.go
+++ b/libgo/go/go/internal/gcimporter/gcimporter_test.go
@@ -141,9 +141,21 @@ func TestVersionHandling(t *testing.T) {
 		}
 		pkgpath := "./" + name[:len(name)-2]
 
+		if testing.Verbose() {
+			t.Logf("importing %s", name)
+		}
+
 		// test that export data can be imported
 		_, err := Import(make(map[string]*types.Package), pkgpath, dir, nil)
 		if err != nil {
+			// ok to fail if it fails with a newer version error for select files
+			if strings.Contains(err.Error(), "newer version") {
+				switch name {
+				case "test_go1.11_999b.a", "test_go1.11_999i.a":
+					continue
+				}
+				// fall through
+			}
 			t.Errorf("import %q failed: %v", pkgpath, err)
 			continue
 		}
@@ -200,11 +212,24 @@ var importedObjectTests = []struct {
 	name string
 	want string
 }{
+	// non-interfaces
+	{"crypto.Hash", "type Hash uint"},
+	{"go/ast.ObjKind", "type ObjKind int"},
+	{"go/types.Qualifier", "type Qualifier func(*Package) string"},
+	{"go/types.Comparable", "func Comparable(T Type) bool"},
 	{"math.Pi", "const Pi untyped float"},
+	{"math.Sin", "func Sin(x float64) float64"},
+	{"go/ast.NotNilFilter", "func NotNilFilter(_ string, v reflect.Value) bool"},
+	{"go/internal/gcimporter.BImportData", "func BImportData(fset *go/token.FileSet, imports map[string]*go/types.Package, data []byte, path string) (_ int, pkg *go/types.Package, err error)"},
+
+	// interfaces
+	{"context.Context", "type Context interface{Deadline() (deadline time.Time, ok bool); Done() <-chan struct{}; Err() error; Value(key interface{}) interface{}}"},
+	{"crypto.Decrypter", "type Decrypter interface{Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error); Public() PublicKey}"},
+	{"encoding.BinaryMarshaler", "type BinaryMarshaler interface{MarshalBinary() (data []byte, err error)}"},
 	{"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"},
 	{"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"},
-	{"math.Sin", "func Sin(x float64) float64"},
-	// TODO(gri) add more tests
+	{"go/ast.Node", "type Node interface{End() go/token.Pos; Pos() go/token.Pos}"},
+	{"go/types.Type", "type Type interface{String() string; Underlying() Type}"},
 }
 
 func TestImportedTypes(t *testing.T) {
@@ -239,6 +264,46 @@ func TestImportedTypes(t *testing.T) {
 		if got != test.want {
 			t.Errorf("%s: got %q; want %q", test.name, got, test.want)
 		}
+
+		if named, _ := obj.Type().(*types.Named); named != nil {
+			verifyInterfaceMethodRecvs(t, named, 0)
+		}
+	}
+}
+
+// verifyInterfaceMethodRecvs verifies that method receiver types
+// are named if the methods belong to a named interface type.
+func verifyInterfaceMethodRecvs(t *testing.T, named *types.Named, level int) {
+	// avoid endless recursion in case of an embedding bug that lead to a cycle
+	if level > 10 {
+		t.Errorf("%s: embeds itself", named)
+		return
+	}
+
+	iface, _ := named.Underlying().(*types.Interface)
+	if iface == nil {
+		return // not an interface
+	}
+
+	// check explicitly declared methods
+	for i := 0; i < iface.NumExplicitMethods(); i++ {
+		m := iface.ExplicitMethod(i)
+		recv := m.Type().(*types.Signature).Recv()
+		if recv == nil {
+			t.Errorf("%s: missing receiver type", m)
+			continue
+		}
+		if recv.Type() != named {
+			t.Errorf("%s: got recv type %s; want %s", m, recv.Type(), named)
+		}
+	}
+
+	// check embedded interfaces (if they are named, too)
+	for i := 0; i < iface.NumEmbeddeds(); i++ {
+		// embedding of interfaces cannot have cycles; recursion will terminate
+		if etype, _ := iface.EmbeddedType(i).(*types.Named); etype != nil {
+			verifyInterfaceMethodRecvs(t, etype, level+1)
+		}
 	}
 }
 
@@ -456,6 +521,47 @@ func TestIssue20046(t *testing.T) {
 		t.Fatalf("V.M not found (index = %v, indirect = %v)", index, indirect)
 	}
 }
+func TestIssue25301(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+	}
+
+	// On windows, we have to set the -D option for the compiler to avoid having a drive
+	// letter and an illegal ':' in the import path - just skip it (see also issue #3483).
+	if runtime.GOOS == "windows" {
+		t.Skip("avoid dealing with relative paths/drive letters on windows")
+	}
+
+	if f := compile(t, "testdata", "issue25301.go"); f != "" {
+		defer os.Remove(f)
+	}
+
+	importPkg(t, "./testdata/issue25301")
+}
+
+func TestIssue25596(t *testing.T) {
+	skipSpecialPlatforms(t)
+
+	// This package only handles gc export data.
+	if runtime.Compiler != "gc" {
+		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
+	}
+
+	// On windows, we have to set the -D option for the compiler to avoid having a drive
+	// letter and an illegal ':' in the import path - just skip it (see also issue #3483).
+	if runtime.GOOS == "windows" {
+		t.Skip("avoid dealing with relative paths/drive letters on windows")
+	}
+
+	if f := compile(t, "testdata", "issue25596.go"); f != "" {
+		defer os.Remove(f)
+	}
+
+	importPkg(t, "./testdata/issue25596")
+}
 
 func importPkg(t *testing.T, path string) *types.Package {
 	pkg, err := Import(make(map[string]*types.Package), path, ".", nil)
diff --git a/libgo/go/go/internal/gcimporter/iimport.go b/libgo/go/go/internal/gcimporter/iimport.go
new file mode 100644
index 00000000000..bf480641df9
--- /dev/null
+++ b/libgo/go/go/internal/gcimporter/iimport.go
@@ -0,0 +1,596 @@
+// 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.
+
+// Indexed package import.
+// See cmd/compile/internal/gc/iexport.go for the export data format.
+
+package gcimporter
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"go/constant"
+	"go/token"
+	"go/types"
+	"io"
+	"sort"
+)
+
+type intReader struct {
+	*bytes.Reader
+	path string
+}
+
+func (r *intReader) int64() int64 {
+	i, err := binary.ReadVarint(r.Reader)
+	if err != nil {
+		errorf("import %q: read varint error: %v", r.path, err)
+	}
+	return i
+}
+
+func (r *intReader) uint64() uint64 {
+	i, err := binary.ReadUvarint(r.Reader)
+	if err != nil {
+		errorf("import %q: read varint error: %v", r.path, err)
+	}
+	return i
+}
+
+const predeclReserved = 32
+
+type itag uint64
+
+const (
+	// Types
+	definedType itag = iota
+	pointerType
+	sliceType
+	arrayType
+	chanType
+	mapType
+	signatureType
+	structType
+	interfaceType
+)
+
+// iImportData imports a package from the serialized package data
+// 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) {
+	const currentVersion = 0
+	version := -1
+	defer func() {
+		if e := recover(); e != nil {
+			if version > currentVersion {
+				err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
+			} else {
+				err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
+			}
+		}
+	}()
+
+	r := &intReader{bytes.NewReader(data), path}
+
+	version = int(r.uint64())
+	switch version {
+	case currentVersion:
+	default:
+		errorf("unknown iexport format version %d", version)
+	}
+
+	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)
+
+	p := iimporter{
+		ipath: path,
+
+		stringData:  stringData,
+		stringCache: make(map[uint64]string),
+		pkgCache:    make(map[uint64]*types.Package),
+
+		declData: declData,
+		pkgIndex: make(map[*types.Package]map[string]uint64),
+		typCache: make(map[uint64]types.Type),
+
+		fake: fakeFileSet{
+			fset:  fset,
+			files: make(map[string]*token.File),
+		},
+	}
+
+	for i, pt := range predeclared {
+		p.typCache[uint64(i)] = pt
+	}
+
+	pkgList := make([]*types.Package, r.uint64())
+	for i := range pkgList {
+		pkgPathOff := r.uint64()
+		pkgPath := p.stringAt(pkgPathOff)
+		pkgName := p.stringAt(r.uint64())
+		_ = r.uint64() // package height; unused by go/types
+
+		if pkgPath == "" {
+			pkgPath = path
+		}
+		pkg := imports[pkgPath]
+		if pkg == nil {
+			pkg = types.NewPackage(pkgPath, pkgName)
+			imports[pkgPath] = pkg
+		} else if pkg.Name() != pkgName {
+			errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
+		}
+
+		p.pkgCache[pkgPathOff] = pkg
+
+		nameIndex := make(map[string]uint64)
+		for nSyms := r.uint64(); nSyms > 0; nSyms-- {
+			name := p.stringAt(r.uint64())
+			nameIndex[name] = r.uint64()
+		}
+
+		p.pkgIndex[pkg] = nameIndex
+		pkgList[i] = pkg
+	}
+
+	localpkg := pkgList[0]
+
+	names := make([]string, 0, len(p.pkgIndex[localpkg]))
+	for name := range p.pkgIndex[localpkg] {
+		names = append(names, name)
+	}
+	sort.Strings(names)
+	for _, name := range names {
+		p.doDecl(localpkg, name)
+	}
+
+	for _, typ := range p.interfaceList {
+		typ.Complete()
+	}
+
+	// record all referenced packages as imports
+	list := append(([]*types.Package)(nil), pkgList[1:]...)
+	sort.Sort(byPath(list))
+	localpkg.SetImports(list)
+
+	// package was imported completely and without errors
+	localpkg.MarkComplete()
+
+	consumed, _ := r.Seek(0, io.SeekCurrent)
+	return int(consumed), localpkg, nil
+}
+
+type iimporter struct {
+	ipath string
+
+	stringData  []byte
+	stringCache map[uint64]string
+	pkgCache    map[uint64]*types.Package
+
+	declData []byte
+	pkgIndex map[*types.Package]map[string]uint64
+	typCache map[uint64]types.Type
+
+	fake          fakeFileSet
+	interfaceList []*types.Interface
+}
+
+func (p *iimporter) doDecl(pkg *types.Package, name string) {
+	// See if we've already imported this declaration.
+	if obj := pkg.Scope().Lookup(name); obj != nil {
+		return
+	}
+
+	off, ok := p.pkgIndex[pkg][name]
+	if !ok {
+		errorf("%v.%v not in index", pkg, name)
+	}
+
+	r := &importReader{p: p, currPkg: pkg}
+	r.declReader.Reset(p.declData[off:])
+
+	r.obj(name)
+}
+
+func (p *iimporter) stringAt(off uint64) string {
+	if s, ok := p.stringCache[off]; ok {
+		return s
+	}
+
+	slen, n := binary.Uvarint(p.stringData[off:])
+	if n <= 0 {
+		errorf("varint failed")
+	}
+	spos := off + uint64(n)
+	s := string(p.stringData[spos : spos+slen])
+	p.stringCache[off] = s
+	return s
+}
+
+func (p *iimporter) pkgAt(off uint64) *types.Package {
+	if pkg, ok := p.pkgCache[off]; ok {
+		return pkg
+	}
+	path := p.stringAt(off)
+	errorf("missing package %q in %q", path, p.ipath)
+	return nil
+}
+
+func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
+	if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) {
+		return t
+	}
+
+	if off < predeclReserved {
+		errorf("predeclared type missing from cache: %v", off)
+	}
+
+	r := &importReader{p: p}
+	r.declReader.Reset(p.declData[off-predeclReserved:])
+	t := r.doType(base)
+
+	if base == nil || !isInterface(t) {
+		p.typCache[off] = t
+	}
+	return t
+}
+
+type importReader struct {
+	p          *iimporter
+	declReader bytes.Reader
+	currPkg    *types.Package
+	prevFile   string
+	prevLine   int64
+}
+
+func (r *importReader) obj(name string) {
+	tag := r.byte()
+	pos := r.pos()
+
+	switch tag {
+	case 'A':
+		typ := r.typ()
+
+		r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
+
+	case 'C':
+		typ, val := r.value()
+
+		r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
+
+	case 'F':
+		sig := r.signature(nil)
+
+		r.declare(types.NewFunc(pos, r.currPkg, name, sig))
+
+	case 'T':
+		// Types can be recursive. We need to setup a stub
+		// declaration before recursing.
+		obj := types.NewTypeName(pos, r.currPkg, name, nil)
+		named := types.NewNamed(obj, nil, nil)
+		r.declare(obj)
+
+		underlying := r.p.typAt(r.uint64(), named).Underlying()
+		named.SetUnderlying(underlying)
+
+		if !isInterface(underlying) {
+			for n := r.uint64(); n > 0; n-- {
+				mpos := r.pos()
+				mname := r.ident()
+				recv := r.param()
+				msig := r.signature(recv)
+
+				named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
+			}
+		}
+
+	case 'V':
+		typ := r.typ()
+
+		r.declare(types.NewVar(pos, r.currPkg, name, typ))
+
+	default:
+		errorf("unexpected tag: %v", tag)
+	}
+}
+
+func (r *importReader) declare(obj types.Object) {
+	obj.Pkg().Scope().Insert(obj)
+}
+
+func (r *importReader) value() (typ types.Type, val constant.Value) {
+	typ = r.typ()
+
+	switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
+	case types.IsBoolean:
+		val = constant.MakeBool(r.bool())
+
+	case types.IsString:
+		val = constant.MakeString(r.string())
+
+	case types.IsInteger:
+		val = r.mpint(b)
+
+	case types.IsFloat:
+		val = r.mpfloat(b)
+
+	case types.IsComplex:
+		re := r.mpfloat(b)
+		im := r.mpfloat(b)
+		val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
+
+	default:
+		errorf("unexpected type %v", typ) // panics
+		panic("unreachable")
+	}
+
+	return
+}
+
+func intSize(b *types.Basic) (signed bool, maxBytes uint) {
+	if (b.Info() & types.IsUntyped) != 0 {
+		return true, 64
+	}
+
+	switch b.Kind() {
+	case types.Float32, types.Complex64:
+		return true, 3
+	case types.Float64, types.Complex128:
+		return true, 7
+	}
+
+	signed = (b.Info() & types.IsUnsigned) == 0
+	switch b.Kind() {
+	case types.Int8, types.Uint8:
+		maxBytes = 1
+	case types.Int16, types.Uint16:
+		maxBytes = 2
+	case types.Int32, types.Uint32:
+		maxBytes = 4
+	default:
+		maxBytes = 8
+	}
+
+	return
+}
+
+func (r *importReader) mpint(b *types.Basic) constant.Value {
+	signed, maxBytes := intSize(b)
+
+	maxSmall := 256 - maxBytes
+	if signed {
+		maxSmall = 256 - 2*maxBytes
+	}
+	if maxBytes == 1 {
+		maxSmall = 256
+	}
+
+	n, _ := r.declReader.ReadByte()
+	if uint(n) < maxSmall {
+		v := int64(n)
+		if signed {
+			v >>= 1
+			if n&1 != 0 {
+				v = ^v
+			}
+		}
+		return constant.MakeInt64(v)
+	}
+
+	v := -n
+	if signed {
+		v = -(n &^ 1) >> 1
+	}
+	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)
+	if signed && n&1 != 0 {
+		x = constant.UnaryOp(token.SUB, x, 0)
+	}
+	return x
+}
+
+func (r *importReader) mpfloat(b *types.Basic) constant.Value {
+	x := r.mpint(b)
+	if constant.Sign(x) == 0 {
+		return x
+	}
+
+	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
+}
+
+func (r *importReader) ident() string {
+	return r.string()
+}
+
+func (r *importReader) qualifiedIdent() (*types.Package, string) {
+	name := r.string()
+	pkg := r.pkg()
+	return pkg, name
+}
+
+func (r *importReader) pos() token.Pos {
+	delta := r.int64()
+	if delta != deltaNewFile {
+		r.prevLine += delta
+	} else if l := r.int64(); l == -1 {
+		r.prevLine += deltaNewFile
+	} else {
+		r.prevFile = r.string()
+		r.prevLine = l
+	}
+
+	if r.prevFile == "" && r.prevLine == 0 {
+		return token.NoPos
+	}
+
+	return r.p.fake.pos(r.prevFile, int(r.prevLine))
+}
+
+func (r *importReader) typ() types.Type {
+	return r.p.typAt(r.uint64(), nil)
+}
+
+func isInterface(t types.Type) bool {
+	_, ok := t.(*types.Interface)
+	return ok
+}
+
+func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
+func (r *importReader) string() string      { return r.p.stringAt(r.uint64()) }
+
+func (r *importReader) doType(base *types.Named) types.Type {
+	switch k := r.kind(); k {
+	default:
+		errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
+		return nil
+
+	case definedType:
+		pkg, name := r.qualifiedIdent()
+		r.p.doDecl(pkg, name)
+		return pkg.Scope().Lookup(name).(*types.TypeName).Type()
+	case pointerType:
+		return types.NewPointer(r.typ())
+	case sliceType:
+		return types.NewSlice(r.typ())
+	case arrayType:
+		n := r.uint64()
+		return types.NewArray(r.typ(), int64(n))
+	case chanType:
+		dir := chanDir(int(r.uint64()))
+		return types.NewChan(dir, r.typ())
+	case mapType:
+		return types.NewMap(r.typ(), r.typ())
+	case signatureType:
+		r.currPkg = r.pkg()
+		return r.signature(nil)
+
+	case structType:
+		r.currPkg = r.pkg()
+
+		fields := make([]*types.Var, r.uint64())
+		tags := make([]string, len(fields))
+		for i := range fields {
+			fpos := r.pos()
+			fname := r.ident()
+			ftyp := r.typ()
+			emb := r.bool()
+			tag := r.string()
+
+			fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
+			tags[i] = tag
+		}
+		return types.NewStruct(fields, tags)
+
+	case interfaceType:
+		r.currPkg = r.pkg()
+
+		embeddeds := make([]types.Type, r.uint64())
+		for i := range embeddeds {
+			_ = r.pos()
+			embeddeds[i] = r.typ()
+		}
+
+		methods := make([]*types.Func, r.uint64())
+		for i := range methods {
+			mpos := r.pos()
+			mname := r.ident()
+
+			// TODO(mdempsky): Matches bimport.go, but I
+			// don't agree with this.
+			var recv *types.Var
+			if base != nil {
+				recv = types.NewVar(token.NoPos, r.currPkg, "", base)
+			}
+
+			msig := r.signature(recv)
+			methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
+		}
+
+		typ := types.NewInterfaceType(methods, embeddeds)
+		r.p.interfaceList = append(r.p.interfaceList, typ)
+		return typ
+	}
+}
+
+func (r *importReader) kind() itag {
+	return itag(r.uint64())
+}
+
+func (r *importReader) signature(recv *types.Var) *types.Signature {
+	params := r.paramList()
+	results := r.paramList()
+	variadic := params.Len() > 0 && r.bool()
+	return types.NewSignature(recv, params, results, variadic)
+}
+
+func (r *importReader) paramList() *types.Tuple {
+	xs := make([]*types.Var, r.uint64())
+	for i := range xs {
+		xs[i] = r.param()
+	}
+	return types.NewTuple(xs...)
+}
+
+func (r *importReader) param() *types.Var {
+	pos := r.pos()
+	name := r.ident()
+	typ := r.typ()
+	return types.NewParam(pos, r.currPkg, name, typ)
+}
+
+func (r *importReader) bool() bool {
+	return r.uint64() != 0
+}
+
+func (r *importReader) int64() int64 {
+	n, err := binary.ReadVarint(&r.declReader)
+	if err != nil {
+		errorf("readVarint: %v", err)
+	}
+	return n
+}
+
+func (r *importReader) uint64() uint64 {
+	n, err := binary.ReadUvarint(&r.declReader)
+	if err != nil {
+		errorf("readUvarint: %v", err)
+	}
+	return n
+}
+
+func (r *importReader) byte() byte {
+	x, err := r.declReader.ReadByte()
+	if err != nil {
+		errorf("declReader.ReadByte: %v", err)
+	}
+	return x
+}
diff --git a/libgo/go/go/internal/gcimporter/testdata/issue25301.go b/libgo/go/go/internal/gcimporter/testdata/issue25301.go
new file mode 100644
index 00000000000..e3dc98b4e1f
--- /dev/null
+++ b/libgo/go/go/internal/gcimporter/testdata/issue25301.go
@@ -0,0 +1,17 @@
+// 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 issue25301
+
+type (
+	A = interface {
+		M()
+	}
+	T interface {
+		A
+	}
+	S struct{}
+)
+
+func (S) M() { println("m") }
diff --git a/libgo/go/go/internal/gcimporter/testdata/issue25596.go b/libgo/go/go/internal/gcimporter/testdata/issue25596.go
new file mode 100644
index 00000000000..8923373e5fa
--- /dev/null
+++ b/libgo/go/go/internal/gcimporter/testdata/issue25596.go
@@ -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.
+
+package issue25596
+
+type E interface {
+	M() T
+}
+
+type T interface {
+	E
+}
diff --git a/libgo/go/go/internal/gcimporter/testdata/versions/test.go b/libgo/go/go/internal/gcimporter/testdata/versions/test.go
index ac9c968c2d0..227fc092519 100644
--- a/libgo/go/go/internal/gcimporter/testdata/versions/test.go
+++ b/libgo/go/go/internal/gcimporter/testdata/versions/test.go
@@ -11,7 +11,10 @@
 //
 // go build -o test_go1.$X_$Y.a test.go
 //
-// with $X = Go version and $Y = export format version.
+// with $X = Go version and $Y = export format version
+// (add 'b' or 'i' to distinguish between binary and
+// indexed format starting with 1.11 as long as both
+// formats are supported).
 //
 // Make sure this source is extended such that it exercises
 // whatever export format change has taken place.
diff --git a/libgo/go/go/internal/srcimporter/srcimporter.go b/libgo/go/go/internal/srcimporter/srcimporter.go
index 9ed7e5e4dca..2a6c274424d 100644
--- a/libgo/go/go/internal/srcimporter/srcimporter.go
+++ b/libgo/go/go/internal/srcimporter/srcimporter.go
@@ -13,6 +13,8 @@ import (
 	"go/parser"
 	"go/token"
 	"go/types"
+	"io"
+	"os"
 	"path/filepath"
 	"sync"
 )
@@ -144,7 +146,11 @@ func (p *Importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*type
 }
 
 func (p *Importer) parseFiles(dir string, filenames []string) ([]*ast.File, error) {
-	open := p.ctxt.OpenFile // possibly nil
+	// use build.Context's OpenFile if there is one
+	open := p.ctxt.OpenFile
+	if open == nil {
+		open = func(name string) (io.ReadCloser, error) { return os.Open(name) }
+	}
 
 	files := make([]*ast.File, len(filenames))
 	errors := make([]error, len(filenames))
@@ -154,22 +160,13 @@ func (p *Importer) parseFiles(dir string, filenames []string) ([]*ast.File, erro
 	for i, filename := range filenames {
 		go func(i int, filepath string) {
 			defer wg.Done()
-			if open != nil {
-				src, err := open(filepath)
-				if err != nil {
-					errors[i] = fmt.Errorf("opening package file %s failed (%v)", filepath, err)
-					return
-				}
-				files[i], errors[i] = parser.ParseFile(p.fset, filepath, src, 0)
-				src.Close() // ignore Close error - parsing may have succeeded which is all we need
-			} else {
-				// Special-case when ctxt doesn't provide a custom OpenFile and use the
-				// parser's file reading mechanism directly. This appears to be quite a
-				// bit faster than opening the file and providing an io.ReaderCloser in
-				// both cases.
-				// TODO(gri) investigate performance difference (issue #19281)
-				files[i], errors[i] = parser.ParseFile(p.fset, filepath, nil, 0)
+			src, err := open(filepath)
+			if err != nil {
+				errors[i] = err // open provides operation and filename in error
+				return
 			}
+			files[i], errors[i] = parser.ParseFile(p.fset, filepath, src, 0)
+			src.Close() // ignore Close error - parsing may have succeeded which is all we need
 		}(i, p.joinPath(dir, filename))
 	}
 	wg.Wait()
diff --git a/libgo/go/go/internal/srcimporter/srcimporter_test.go b/libgo/go/go/internal/srcimporter/srcimporter_test.go
index dd4d56ad17d..b9caa90fc58 100644
--- a/libgo/go/go/internal/srcimporter/srcimporter_test.go
+++ b/libgo/go/go/internal/srcimporter/srcimporter_test.go
@@ -131,6 +131,44 @@ func TestImportedTypes(t *testing.T) {
 		if got != test.want {
 			t.Errorf("%s: got %q; want %q", test.name, got, test.want)
 		}
+
+		if named, _ := obj.Type().(*types.Named); named != nil {
+			verifyInterfaceMethodRecvs(t, named, 0)
+		}
+	}
+}
+
+// verifyInterfaceMethodRecvs verifies that method receiver types
+// are named if the methods belong to a named interface type.
+func verifyInterfaceMethodRecvs(t *testing.T, named *types.Named, level int) {
+	// avoid endless recursion in case of an embedding bug that lead to a cycle
+	if level > 10 {
+		t.Errorf("%s: embeds itself", named)
+		return
+	}
+
+	iface, _ := named.Underlying().(*types.Interface)
+	if iface == nil {
+		return // not an interface
+	}
+
+	// check explicitly declared methods
+	for i := 0; i < iface.NumExplicitMethods(); i++ {
+		m := iface.ExplicitMethod(i)
+		recv := m.Type().(*types.Signature).Recv()
+		if recv == nil {
+			t.Errorf("%s: missing receiver type", m)
+			continue
+		}
+		if recv.Type() != named {
+			t.Errorf("%s: got recv type %s; want %s", m, recv.Type(), named)
+		}
+	}
+
+	// check embedded interfaces (they are named, too)
+	for i := 0; i < iface.NumEmbeddeds(); i++ {
+		// embedding of interfaces cannot have cycles; recursion will terminate
+		verifyInterfaceMethodRecvs(t, iface.Embedded(i), level+1)
 	}
 }
 
diff --git a/libgo/go/go/parser/error_test.go b/libgo/go/go/parser/error_test.go
index ef91e1ea60e..9b79097acf6 100644
--- a/libgo/go/go/parser/error_test.go
+++ b/libgo/go/go/parser/error_test.go
@@ -91,6 +91,12 @@ func expectedErrors(fset *token.FileSet, filename string, src []byte) map[token.
 				}
 				errors[pos] = string(s[2])
 			}
+		case token.SEMICOLON:
+			// don't use the position of auto-inserted (invisible) semicolons
+			if lit != ";" {
+				break
+			}
+			fallthrough
 		default:
 			prev = pos
 			var l int // token length
diff --git a/libgo/go/go/parser/interface.go b/libgo/go/go/parser/interface.go
index 724d8658a7d..9de160a7988 100644
--- a/libgo/go/go/parser/interface.go
+++ b/libgo/go/go/parser/interface.go
@@ -35,11 +35,7 @@ func readSource(filename string, src interface{}) ([]byte, error) {
 				return s.Bytes(), nil
 			}
 		case io.Reader:
-			var buf bytes.Buffer
-			if _, err := io.Copy(&buf, s); err != nil {
-				return nil, err
-			}
-			return buf.Bytes(), nil
+			return ioutil.ReadAll(s)
 		}
 		return nil, errors.New("invalid source")
 	}
diff --git a/libgo/go/go/parser/parser.go b/libgo/go/go/parser/parser.go
index 2b58724521f..189bfb42236 100644
--- a/libgo/go/go/parser/parser.go
+++ b/libgo/go/go/parser/parser.go
@@ -48,11 +48,11 @@ type parser struct {
 	lit string      // token literal
 
 	// Error recovery
-	// (used to limit the number of calls to syncXXX functions
+	// (used to limit the number of calls to parser.advance
 	// w/o making scanning progress - avoids potential endless
 	// loops across multiple parser functions during error recovery)
 	syncPos token.Pos // last synchronization position
-	syncCnt int       // number of calls to syncXXX without progress
+	syncCnt int       // number of parser.advance calls without progress
 
 	// Non-syntactic parser control
 	exprLev int  // < 0: in control clause, >= 0: in expression
@@ -375,13 +375,14 @@ func (p *parser) errorExpected(pos token.Pos, msg string) {
 	if pos == p.pos {
 		// the error happened at the current position;
 		// make the error message more specific
-		if p.tok == token.SEMICOLON && p.lit == "\n" {
+		switch {
+		case p.tok == token.SEMICOLON && p.lit == "\n":
 			msg += ", found newline"
-		} else {
+		case p.tok.IsLiteral():
+			// print 123 rather than 'INT', etc.
+			msg += ", found " + p.lit
+		default:
 			msg += ", found '" + p.tok.String() + "'"
-			if p.tok.IsLiteral() {
-				msg += " " + p.lit
-			}
 		}
 	}
 	p.error(pos, msg)
@@ -419,7 +420,7 @@ func (p *parser) expectSemi() {
 			p.next()
 		default:
 			p.errorExpected(p.pos, "';'")
-			syncStmt(p)
+			p.advance(stmtStart)
 		}
 	}
 }
@@ -445,21 +446,16 @@ func assert(cond bool, msg string) {
 	}
 }
 
-// syncStmt advances to the next statement.
-// Used for synchronization after an error.
-//
-func syncStmt(p *parser) {
-	for {
-		switch p.tok {
-		case token.BREAK, token.CONST, token.CONTINUE, token.DEFER,
-			token.FALLTHROUGH, token.FOR, token.GO, token.GOTO,
-			token.IF, token.RETURN, token.SELECT, token.SWITCH,
-			token.TYPE, token.VAR:
+// advance consumes tokens until the current token p.tok
+// is in the 'to' set, or token.EOF. For error recovery.
+func (p *parser) advance(to map[token.Token]bool) {
+	for ; p.tok != token.EOF; p.next() {
+		if to[p.tok] {
 			// Return only if parser made some progress since last
-			// sync or if it has not reached 10 sync calls without
+			// sync or if it has not reached 10 advance calls without
 			// progress. Otherwise consume at least one token to
 			// avoid an endless parser loop (it is possible that
-			// both parseOperand and parseStmt call syncStmt and
+			// both parseOperand and parseStmt call advance and
 			// correctly do not advance, thus the need for the
 			// invocation limit p.syncCnt).
 			if p.pos == p.syncPos && p.syncCnt < 10 {
@@ -476,35 +472,40 @@ func syncStmt(p *parser) {
 			// leads to skipping of possibly correct code if a
 			// previous error is present, and thus is preferred
 			// over a non-terminating parse.
-		case token.EOF:
-			return
 		}
-		p.next()
 	}
 }
 
-// syncDecl advances to the next declaration.
-// Used for synchronization after an error.
-//
-func syncDecl(p *parser) {
-	for {
-		switch p.tok {
-		case token.CONST, token.TYPE, token.VAR:
-			// see comments in syncStmt
-			if p.pos == p.syncPos && p.syncCnt < 10 {
-				p.syncCnt++
-				return
-			}
-			if p.pos > p.syncPos {
-				p.syncPos = p.pos
-				p.syncCnt = 0
-				return
-			}
-		case token.EOF:
-			return
-		}
-		p.next()
-	}
+var stmtStart = map[token.Token]bool{
+	token.BREAK:       true,
+	token.CONST:       true,
+	token.CONTINUE:    true,
+	token.DEFER:       true,
+	token.FALLTHROUGH: true,
+	token.FOR:         true,
+	token.GO:          true,
+	token.GOTO:        true,
+	token.IF:          true,
+	token.RETURN:      true,
+	token.SELECT:      true,
+	token.SWITCH:      true,
+	token.TYPE:        true,
+	token.VAR:         true,
+}
+
+var declStart = map[token.Token]bool{
+	token.CONST: true,
+	token.TYPE:  true,
+	token.VAR:   true,
+}
+
+var exprEnd = map[token.Token]bool{
+	token.COMMA:     true,
+	token.COLON:     true,
+	token.SEMICOLON: true,
+	token.RPAREN:    true,
+	token.RBRACK:    true,
+	token.RBRACE:    true,
 }
 
 // safePos returns a valid file position for a given position: If pos
@@ -623,7 +624,7 @@ func (p *parser) parseType() ast.Expr {
 	if typ == nil {
 		pos := p.pos
 		p.errorExpected(pos, "type")
-		p.next() // make progress
+		p.advance(exprEnd)
 		return &ast.BadExpr{From: pos, To: p.pos}
 	}
 
@@ -1166,7 +1167,7 @@ func (p *parser) parseOperand(lhs bool) ast.Expr {
 	// we have an error
 	pos := p.pos
 	p.errorExpected(pos, "operand")
-	syncStmt(p)
+	p.advance(stmtStart)
 	return &ast.BadExpr{From: pos, To: p.pos}
 }
 
@@ -1808,17 +1809,84 @@ func (p *parser) parseBranchStmt(tok token.Token) *ast.BranchStmt {
 	return &ast.BranchStmt{TokPos: pos, Tok: tok, Label: label}
 }
 
-func (p *parser) makeExpr(s ast.Stmt, kind string) ast.Expr {
+func (p *parser) makeExpr(s ast.Stmt, want string) ast.Expr {
 	if s == nil {
 		return nil
 	}
 	if es, isExpr := s.(*ast.ExprStmt); isExpr {
 		return p.checkExpr(es.X)
 	}
-	p.error(s.Pos(), fmt.Sprintf("expected %s, found simple statement (missing parentheses around composite literal?)", kind))
+	found := "simple statement"
+	if _, isAss := s.(*ast.AssignStmt); isAss {
+		found = "assignment"
+	}
+	p.error(s.Pos(), fmt.Sprintf("expected %s, found %s (missing parentheses around composite literal?)", want, found))
 	return &ast.BadExpr{From: s.Pos(), To: p.safePos(s.End())}
 }
 
+// parseIfHeader is an adjusted version of parser.header
+// in cmd/compile/internal/syntax/parser.go, which has
+// been tuned for better error handling.
+func (p *parser) parseIfHeader() (init ast.Stmt, cond ast.Expr) {
+	if p.tok == token.LBRACE {
+		p.error(p.pos, "missing condition in if statement")
+		cond = &ast.BadExpr{From: p.pos, To: p.pos}
+		return
+	}
+	// p.tok != token.LBRACE
+
+	outer := 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"))
+		}
+		init, _ = p.parseSimpleStmt(basic)
+	}
+
+	var condStmt ast.Stmt
+	var semi struct {
+		pos token.Pos
+		lit string // ";" or "\n"; valid if pos.IsValid()
+	}
+	if p.tok != token.LBRACE {
+		if p.tok == token.SEMICOLON {
+			semi.pos = p.pos
+			semi.lit = p.lit
+			p.next()
+		} else {
+			p.expect(token.SEMICOLON)
+		}
+		if p.tok != token.LBRACE {
+			condStmt, _ = p.parseSimpleStmt(basic)
+		}
+	} else {
+		condStmt = init
+		init = nil
+	}
+
+	if condStmt != nil {
+		cond = p.makeExpr(condStmt, "boolean expression")
+	} else if semi.pos.IsValid() {
+		if semi.lit == "\n" {
+			p.error(semi.pos, "unexpected newline, expecting { after if clause")
+		} else {
+			p.error(semi.pos, "missing condition in if statement")
+		}
+	}
+
+	// make sure we have a valid AST
+	if cond == nil {
+		cond = &ast.BadExpr{From: p.pos, To: p.pos}
+	}
+
+	p.exprLev = outer
+	return
+}
+
 func (p *parser) parseIfStmt() *ast.IfStmt {
 	if p.trace {
 		defer un(trace(p, "IfStmt"))
@@ -1828,28 +1896,9 @@ func (p *parser) parseIfStmt() *ast.IfStmt {
 	p.openScope()
 	defer p.closeScope()
 
-	var s ast.Stmt
-	var x ast.Expr
-	{
-		prevLev := p.exprLev
-		p.exprLev = -1
-		if p.tok == token.SEMICOLON {
-			p.next()
-			x = p.parseRhs()
-		} else {
-			s, _ = p.parseSimpleStmt(basic)
-			if p.tok == token.SEMICOLON {
-				p.next()
-				x = p.parseRhs()
-			} else {
-				x = p.makeExpr(s, "boolean expression")
-				s = nil
-			}
-		}
-		p.exprLev = prevLev
-	}
-
+	init, cond := p.parseIfHeader()
 	body := p.parseBlockStmt()
+
 	var else_ ast.Stmt
 	if p.tok == token.ELSE {
 		p.next()
@@ -1867,7 +1916,7 @@ func (p *parser) parseIfStmt() *ast.IfStmt {
 		p.expectSemi()
 	}
 
-	return &ast.IfStmt{If: pos, Init: s, Cond: x, Body: body, Else: else_}
+	return &ast.IfStmt{If: pos, Init: init, Cond: cond, Body: body, Else: else_}
 }
 
 func (p *parser) parseTypeList() (list []ast.Expr) {
@@ -2160,7 +2209,7 @@ func (p *parser) parseStmt() (s ast.Stmt) {
 
 	switch p.tok {
 	case token.CONST, token.TYPE, token.VAR:
-		s = &ast.DeclStmt{Decl: p.parseDecl(syncStmt)}
+		s = &ast.DeclStmt{Decl: p.parseDecl(stmtStart)}
 	case
 		// tokens that may start an expression
 		token.IDENT, token.INT, token.FLOAT, token.IMAG, token.CHAR, token.STRING, token.FUNC, token.LPAREN, // operands
@@ -2205,7 +2254,7 @@ func (p *parser) parseStmt() (s ast.Stmt) {
 		// no statement found
 		pos := p.pos
 		p.errorExpected(pos, "statement")
-		syncStmt(p)
+		p.advance(stmtStart)
 		s = &ast.BadStmt{From: pos, To: p.pos}
 	}
 
@@ -2419,7 +2468,7 @@ func (p *parser) parseFuncDecl() *ast.FuncDecl {
 	return decl
 }
 
-func (p *parser) parseDecl(sync func(*parser)) ast.Decl {
+func (p *parser) parseDecl(sync map[token.Token]bool) ast.Decl {
 	if p.trace {
 		defer un(trace(p, "Declaration"))
 	}
@@ -2438,7 +2487,7 @@ func (p *parser) parseDecl(sync func(*parser)) ast.Decl {
 	default:
 		pos := p.pos
 		p.errorExpected(pos, "declaration")
-		sync(p)
+		p.advance(sync)
 		return &ast.BadDecl{From: pos, To: p.pos}
 	}
 
@@ -2488,7 +2537,7 @@ func (p *parser) parseFile() *ast.File {
 		if p.mode&ImportsOnly == 0 {
 			// rest of package body
 			for p.tok != token.EOF {
-				decls = append(decls, p.parseDecl(syncDecl))
+				decls = append(decls, p.parseDecl(declStart))
 			}
 		}
 	}
diff --git a/libgo/go/go/parser/short_test.go b/libgo/go/go/parser/short_test.go
index 6f8ef6b0f77..49bb681e09e 100644
--- a/libgo/go/go/parser/short_test.go
+++ b/libgo/go/go/parser/short_test.go
@@ -58,10 +58,10 @@ func TestValid(t *testing.T) {
 
 var invalids = []string{
 	`foo /* ERROR "expected 'package'" */ !`,
-	`package p; func f() { if { /* ERROR "expected operand" */ } };`,
-	`package p; func f() { if ; { /* ERROR "expected operand" */ } };`,
-	`package p; func f() { if f(); { /* ERROR "expected operand" */ } };`,
-	`package p; func f() { if _ /* ERROR "expected boolean expression" */ = range x; true {} };`,
+	`package p; func f() { if { /* ERROR "missing condition" */ } };`,
+	`package p; func f() { if ; /* ERROR "missing condition" */ {} };`,
+	`package p; func f() { if f(); /* ERROR "missing condition" */ {} };`,
+	`package p; func f() { if _ = range /* ERROR "expected operand" */ x; true {} };`,
 	`package p; func f() { switch _ /* ERROR "expected switch expression" */ = range x; true {} };`,
 	`package p; func f() { for _ = range x ; /* ERROR "expected '{'" */ ; {} };`,
 	`package p; func f() { for ; ; _ = range /* ERROR "expected operand" */ x {} };`,
@@ -85,7 +85,7 @@ var invalids = []string{
 	`package p; func f() { _ = (<-<- /* ERROR "expected 'chan'" */ chan int)(nil) };`,
 	`package p; func f() { _ = (<-chan<-chan<-chan<-chan<-chan<- /* ERROR "expected channel type" */ int)(nil) };`,
 	`package p; func f() { var t []int; t /* ERROR "expected identifier on left side of :=" */ [0] := 0 };`,
-	`package p; func f() { if x := g(); x = /* ERROR "expected '=='" */ 0 {}};`,
+	`package p; func f() { if x := g(); x /* ERROR "expected boolean expression" */ = 0 {}};`,
 	`package p; func f() { _ = x = /* ERROR "expected '=='" */ 0 {}};`,
 	`package p; func f() { _ = 1 == func()int { var x bool; x = x = /* ERROR "expected '=='" */ true; return x }() };`,
 	`package p; func f() { var s []int; _ = s[] /* ERROR "expected operand" */ };`,
diff --git a/libgo/go/go/parser/testdata/commas.src b/libgo/go/go/parser/testdata/commas.src
index af6e7064506..e0603cf9f77 100644
--- a/libgo/go/go/parser/testdata/commas.src
+++ b/libgo/go/go/parser/testdata/commas.src
@@ -8,12 +8,12 @@
 package p
 
 var _ = []int{
-	0 /* ERROR "missing ','" */
+	0/* ERROR HERE "missing ','" */
 }
 
 var _ = []int{
 	0,
 	1,
 	2,
-	3 /* ERROR "missing ','" */
+	3/* ERROR HERE "missing ','" */
 }
diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go
index 3e2ff4f5ae3..1de7cd81b2c 100644
--- a/libgo/go/go/printer/nodes.go
+++ b/libgo/go/go/printer/nodes.go
@@ -12,6 +12,7 @@ import (
 	"bytes"
 	"go/ast"
 	"go/token"
+	"math"
 	"strconv"
 	"strings"
 	"unicode"
@@ -31,8 +32,10 @@ import (
 
 // Print as many newlines as necessary (but at least min newlines) to get to
 // the current line. ws is printed before the first line break. If newSection
-// is set, the first line break is printed as formfeed. Returns true if any
-// line break was printed; returns false otherwise.
+// is set, the first line break is printed as formfeed. Returns 0 if no line
+// breaks were printed, returns 1 if there was exactly one newline printed,
+// and returns a value > 1 if there was a formfeed or more than one newline
+// printed.
 //
 // TODO(gri): linebreak may add too many lines if the next statement at "line"
 //            is preceded by comments because the computation of n assumes
@@ -42,7 +45,7 @@ import (
 //            linebreaks. At the moment there is no easy way to know about
 //            future (not yet interspersed) comments in this function.
 //
-func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (printedBreak bool) {
+func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (nbreaks int) {
 	n := nlimit(line - p.pos.Line)
 	if n < min {
 		n = min
@@ -52,11 +55,12 @@ func (p *printer) linebreak(line, min int, ws whiteSpace, newSection bool) (prin
 		if newSection {
 			p.print(formfeed)
 			n--
+			nbreaks = 2
 		}
+		nbreaks += n
 		for ; n > 0; n-- {
 			p.print(newline)
 		}
-		printedBreak = true
 	}
 	return
 }
@@ -111,9 +115,11 @@ func (p *printer) identList(list []*ast.Ident, indent bool) {
 	if !indent {
 		mode = noIndent
 	}
-	p.exprList(token.NoPos, xlist, 1, mode, token.NoPos)
+	p.exprList(token.NoPos, xlist, 1, mode, token.NoPos, false)
 }
 
+const filteredMsg = "contains filtered or unexported fields"
+
 // Print a list of expressions. If the list spans multiple
 // source lines, the original line breaks are respected between
 // expressions.
@@ -121,8 +127,18 @@ func (p *printer) identList(list []*ast.Ident, indent bool) {
 // TODO(gri) Consider rewriting this to be independent of []ast.Expr
 //           so that we can use the algorithm for any kind of list
 //           (e.g., pass list via a channel over which to range).
-func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exprListMode, next0 token.Pos) {
+func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exprListMode, next0 token.Pos, isIncomplete bool) {
 	if len(list) == 0 {
+		if isIncomplete {
+			prev := p.posFor(prev0)
+			next := p.posFor(next0)
+			if prev.IsValid() && prev.Line == next.Line {
+				p.print("/* " + filteredMsg + " */")
+			} else {
+				p.print(newline)
+				p.print(indent, "// "+filteredMsg, unindent, newline)
+			}
+		}
 		return
 	}
 
@@ -141,23 +157,26 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
 			}
 			p.expr0(x, depth)
 		}
+		if isIncomplete {
+			p.print(token.COMMA, blank, "/* "+filteredMsg+" */")
+		}
 		return
 	}
 
 	// list entries span multiple lines;
 	// use source code positions to guide line breaks
 
-	// don't add extra indentation if noIndent is set;
-	// i.e., pretend that the first line is already indented
+	// Don't add extra indentation if noIndent is set;
+	// i.e., pretend that the first line is already indented.
 	ws := ignore
 	if mode&noIndent == 0 {
 		ws = indent
 	}
 
-	// the first linebreak is always a formfeed since this section must not
-	// depend on any previous formatting
+	// The first linebreak is always a formfeed since this section must not
+	// depend on any previous formatting.
 	prevBreak := -1 // index of last expression that was followed by a linebreak
-	if prev.IsValid() && prev.Line < line && p.linebreak(line, 0, ws, true) {
+	if prev.IsValid() && prev.Line < line && p.linebreak(line, 0, ws, true) > 0 {
 		ws = ignore
 		prevBreak = 0
 	}
@@ -165,22 +184,29 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
 	// initialize expression/key size: a zero value indicates expr/key doesn't fit on a single line
 	size := 0
 
+	// We use the ratio between the geometric mean of the previous key sizes and
+	// the current size to determine if there should be a break in the alignment.
+	// To compute the geometric mean we accumulate the ln(size) values (lnsum)
+	// and the number of sizes included (count).
+	lnsum := 0.0
+	count := 0
+
 	// print all list elements
 	prevLine := prev.Line
 	for i, x := range list {
 		line = p.lineFor(x.Pos())
 
-		// determine if the next linebreak, if any, needs to use formfeed:
+		// Determine if the next linebreak, if any, needs to use formfeed:
 		// in general, use the entire node size to make the decision; for
-		// key:value expressions, use the key size
+		// key:value expressions, use the key size.
 		// TODO(gri) for a better result, should probably incorporate both
 		//           the key and the node size into the decision process
 		useFF := true
 
-		// determine element size: all bets are off if we don't have
+		// Determine element size: All bets are off if we don't have
 		// position information for the previous and next token (likely
 		// generated code - simply ignore the size in this case by setting
-		// it to 0)
+		// it to 0).
 		prevSize := size
 		const infinity = 1e6 // larger than any source line
 		size = p.nodeSize(x, infinity)
@@ -195,40 +221,51 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
 			size = 0
 		}
 
-		// if the previous line and the current line had single-
+		// If the previous line and the current line had single-
 		// line-expressions and the key sizes are small or the
-		// the ratio between the key sizes does not exceed a
-		// threshold, align columns and do not use formfeed
+		// ratio between the current key and the geometric mean
+		// if the previous key sizes does not exceed a threshold,
+		// align columns and do not use formfeed.
 		if prevSize > 0 && size > 0 {
-			const smallSize = 20
-			if prevSize <= smallSize && size <= smallSize {
+			const smallSize = 40
+			if count == 0 || prevSize <= smallSize && size <= smallSize {
 				useFF = false
 			} else {
-				const r = 4 // threshold
-				ratio := float64(size) / float64(prevSize)
-				useFF = ratio <= 1.0/r || r <= ratio
+				const r = 2.5                               // threshold
+				geomean := math.Exp(lnsum / float64(count)) // count > 0
+				ratio := float64(size) / geomean
+				useFF = r*ratio <= 1 || r <= ratio
 			}
 		}
 
 		needsLinebreak := 0 < prevLine && prevLine < line
 		if i > 0 {
-			// use position of expression following the comma as
+			// Use position of expression following the comma as
 			// comma position for correct comment placement, but
-			// only if the expression is on the same line
+			// only if the expression is on the same line.
 			if !needsLinebreak {
 				p.print(x.Pos())
 			}
 			p.print(token.COMMA)
 			needsBlank := true
 			if needsLinebreak {
-				// lines are broken using newlines so comments remain aligned
-				// unless forceFF is set or there are multiple expressions on
-				// the same line in which case formfeed is used
-				if p.linebreak(line, 0, ws, useFF || prevBreak+1 < i) {
+				// Lines are broken using newlines so comments remain aligned
+				// unless useFF is set or there are multiple expressions on
+				// the same line in which case formfeed is used.
+				nbreaks := p.linebreak(line, 0, ws, useFF || prevBreak+1 < i)
+				if nbreaks > 0 {
 					ws = ignore
 					prevBreak = i
 					needsBlank = false // we got a line break instead
 				}
+				// If there was a new section or more than one new line
+				// (which means that the tabwriter will implicitly break
+				// the section), reset the geomean variables since we are
+				// starting a new group of elements with the next element.
+				if nbreaks > 1 {
+					lnsum = 0
+					count = 0
+				}
 			}
 			if needsBlank {
 				p.print(blank)
@@ -236,10 +273,10 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
 		}
 
 		if len(list) > 1 && isPair && size > 0 && needsLinebreak {
-			// we have a key:value expression that fits onto one line
+			// We have a key:value expression that fits onto one line
 			// and it's not on the same line as the prior expression:
-			// use a column for the key such that consecutive entries
-			// can align if possible
+			// Use a column for the key such that consecutive entries
+			// can align if possible.
 			// (needsLinebreak is set if we started a new line before)
 			p.expr(pair.Key)
 			p.print(pair.Colon, token.COLON, vtab)
@@ -248,12 +285,21 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
 			p.expr0(x, depth)
 		}
 
+		if size > 0 {
+			lnsum += math.Log(float64(size))
+			count++
+		}
+
 		prevLine = line
 	}
 
 	if mode&commaTerm != 0 && next.IsValid() && p.pos.Line < next.Line {
-		// print a terminating comma if the next token is on a new line
+		// Print a terminating comma if the next token is on a new line.
 		p.print(token.COMMA)
+		if isIncomplete {
+			p.print(newline)
+			p.print("// " + filteredMsg)
+		}
 		if ws == ignore && mode&noIndent == 0 {
 			// unindent if we indented
 			p.print(unindent)
@@ -262,6 +308,11 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
 		return
 	}
 
+	if isIncomplete {
+		p.print(token.COMMA, newline)
+		p.print("// "+filteredMsg, newline)
+	}
+
 	if ws == ignore && mode&noIndent == 0 {
 		// unindent if we indented
 		p.print(unindent)
@@ -296,7 +347,7 @@ func (p *printer) parameters(fields *ast.FieldList) {
 				p.print(token.COMMA)
 			}
 			// separator if needed (linebreak or blank)
-			if needsLinebreak && p.linebreak(parLineBeg, 0, ws, true) {
+			if needsLinebreak && p.linebreak(parLineBeg, 0, ws, true) > 0 {
 				// break line if the opening "(" or previous parameter ended on a different line
 				ws = ignore
 			} else if i > 0 {
@@ -481,7 +532,7 @@ func (p *printer) fieldList(fields *ast.FieldList, isStruct, isIncomplete bool)
 				p.print(formfeed)
 			}
 			p.flush(p.posFor(rbrace), token.RBRACE) // make sure we don't lose the last line comment
-			p.setLineComment("// contains filtered or unexported fields")
+			p.setLineComment("// " + filteredMsg)
 		}
 
 	} else { // interface
@@ -667,7 +718,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int) {
 	if xline != yline && xline > 0 && yline > 0 {
 		// at least one line break, but respect an extra empty line
 		// in the source
-		if p.linebreak(yline, 1, ws, true) {
+		if p.linebreak(yline, 1, ws, true) > 0 {
 			ws = ignore
 			printBlank = false // no blank after line break
 		}
@@ -833,13 +884,13 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
 		}
 		p.print(x.Lparen, token.LPAREN)
 		if x.Ellipsis.IsValid() {
-			p.exprList(x.Lparen, x.Args, depth, 0, x.Ellipsis)
+			p.exprList(x.Lparen, x.Args, depth, 0, x.Ellipsis, false)
 			p.print(x.Ellipsis, token.ELLIPSIS)
 			if x.Rparen.IsValid() && p.lineFor(x.Ellipsis) < p.lineFor(x.Rparen) {
 				p.print(token.COMMA, formfeed)
 			}
 		} else {
-			p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen)
+			p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen, false)
 		}
 		p.print(x.Rparen, token.RPAREN)
 		if wasIndented {
@@ -853,7 +904,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
 		}
 		p.level++
 		p.print(x.Lbrace, token.LBRACE)
-		p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace)
+		p.exprList(x.Lbrace, x.Elts, 1, commaTerm, x.Rbrace, x.Incomplete)
 		// do not insert extra line break following a /*-style comment
 		// before the closing '}' as it might break the code if there
 		// is no trailing ','
@@ -1163,9 +1214,9 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
 		if len(s.Lhs) > 1 && len(s.Rhs) > 1 {
 			depth++
 		}
-		p.exprList(s.Pos(), s.Lhs, depth, 0, s.TokPos)
+		p.exprList(s.Pos(), s.Lhs, depth, 0, s.TokPos, false)
 		p.print(blank, s.TokPos, s.Tok, blank)
-		p.exprList(s.TokPos, s.Rhs, depth, 0, token.NoPos)
+		p.exprList(s.TokPos, s.Rhs, depth, 0, token.NoPos, false)
 
 	case *ast.GoStmt:
 		p.print(token.GO, blank)
@@ -1186,10 +1237,10 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
 			// lead to more nicely formatted code in general.
 			if p.indentList(s.Results) {
 				p.print(indent)
-				p.exprList(s.Pos(), s.Results, 1, noIndent, token.NoPos)
+				p.exprList(s.Pos(), s.Results, 1, noIndent, token.NoPos, false)
 				p.print(unindent)
 			} else {
-				p.exprList(s.Pos(), s.Results, 1, 0, token.NoPos)
+				p.exprList(s.Pos(), s.Results, 1, 0, token.NoPos, false)
 			}
 		}
 
@@ -1225,7 +1276,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
 	case *ast.CaseClause:
 		if s.List != nil {
 			p.print(token.CASE, blank)
-			p.exprList(s.Pos(), s.List, 1, 0, s.Colon)
+			p.exprList(s.Pos(), s.List, 1, 0, s.Colon, false)
 		} else {
 			p.print(token.DEFAULT)
 		}
@@ -1377,7 +1428,7 @@ func (p *printer) valueSpec(s *ast.ValueSpec, keepType bool) {
 	}
 	if s.Values != nil {
 		p.print(vtab, token.ASSIGN, blank)
-		p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos)
+		p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos, false)
 		extraTabs--
 	}
 	if s.Comment != nil {
@@ -1459,7 +1510,7 @@ func (p *printer) spec(spec ast.Spec, n int, doIndent bool) {
 		}
 		if s.Values != nil {
 			p.print(blank, token.ASSIGN, blank)
-			p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos)
+			p.exprList(token.NoPos, s.Values, 1, 0, token.NoPos, false)
 		}
 		p.setComment(s.Comment)
 
diff --git a/libgo/go/go/printer/printer.go b/libgo/go/go/printer/printer.go
index dbb4bbd90cf..9143442a27c 100644
--- a/libgo/go/go/printer/printer.go
+++ b/libgo/go/go/printer/printer.go
@@ -11,7 +11,6 @@ import (
 	"go/token"
 	"io"
 	"os"
-	"strconv"
 	"strings"
 	"text/tabwriter"
 	"unicode"
@@ -56,14 +55,15 @@ type printer struct {
 	fset *token.FileSet
 
 	// Current state
-	output      []byte       // raw printer result
-	indent      int          // current indentation
-	level       int          // level == 0: outside composite literal; level > 0: inside composite literal
-	mode        pmode        // current printer mode
-	impliedSemi bool         // if set, a linebreak implies a semicolon
-	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
+	output       []byte       // raw printer result
+	indent       int          // current indentation
+	level        int          // level == 0: outside composite literal; level > 0: inside composite literal
+	mode         pmode        // current printer mode
+	endAlignment bool         // if set, terminate alignment immediately
+	impliedSemi  bool         // if set, a linebreak implies a semicolon
+	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
 
 	// Positions
 	// The out position differs from the pos position when the result
@@ -192,13 +192,13 @@ func (p *printer) linesFrom(line int) int {
 
 func (p *printer) posFor(pos token.Pos) token.Position {
 	// not used frequently enough to cache entire token.Position
-	return p.fset.Position(pos)
+	return p.fset.PositionFor(pos, false /* absolute position */)
 }
 
 func (p *printer) lineFor(pos token.Pos) int {
 	if pos != p.cachedPos {
 		p.cachedPos = pos
-		p.cachedLine = p.fset.Position(pos).Line
+		p.cachedLine = p.fset.PositionFor(pos, false /* absolute position */).Line
 	}
 	return p.cachedLine
 }
@@ -233,6 +233,20 @@ func (p *printer) writeIndent() {
 // writeByte writes ch n times to p.output and updates p.pos.
 // Only used to write formatting (white space) characters.
 func (p *printer) writeByte(ch byte, n int) {
+	if p.endAlignment {
+		// Ignore any alignment control character;
+		// and at the end of the line, break with
+		// a formfeed to indicate termination of
+		// existing columns.
+		switch ch {
+		case '\t', '\v':
+			ch = ' '
+		case '\n', '\f':
+			ch = '\f'
+			p.endAlignment = false
+		}
+	}
+
 	if p.out.Column == 1 {
 		// no need to write line directives before white space
 		p.writeIndent()
@@ -299,10 +313,15 @@ func (p *printer) writeString(pos token.Position, s string, isLit bool) {
 	nlines := 0
 	var li int // index of last newline; valid if nlines > 0
 	for i := 0; i < len(s); i++ {
-		// Go tokens cannot contain '\f' - no need to look for it
-		if s[i] == '\n' {
+		// Raw string literals may contain any character except back quote (`).
+		if ch := s[i]; ch == '\n' || ch == '\f' {
+			// account for line break
 			nlines++
 			li = i
+			// A line break inside a literal will break whatever column
+			// formatting is in place; ignore any further alignment through
+			// the end of the line.
+			p.endAlignment = true
 		}
 	}
 	p.pos.Offset += len(s)
@@ -622,24 +641,10 @@ func (p *printer) writeComment(comment *ast.Comment) {
 
 	const linePrefix = "//line "
 	if strings.HasPrefix(text, linePrefix) && (!pos.IsValid() || pos.Column == 1) {
-		// possibly a line directive
-		ldir := strings.TrimSpace(text[len(linePrefix):])
-		if i := strings.LastIndex(ldir, ":"); i >= 0 {
-			if line, err := strconv.Atoi(ldir[i+1:]); err == nil && line > 0 {
-				// The line directive we are about to print changed
-				// the Filename and Line number used for subsequent
-				// tokens. We have to update our AST-space position
-				// accordingly and suspend indentation temporarily.
-				indent := p.indent
-				p.indent = 0
-				defer func() {
-					p.pos.Filename = ldir[:i]
-					p.pos.Line = line
-					p.pos.Column = 1
-					p.indent = indent
-				}()
-			}
-		}
+		// Possibly a //-style line directive.
+		// Suspend indentation temporarily to keep line directive valid.
+		defer func(indent int) { p.indent = indent }(p.indent)
+		p.indent = 0
 	}
 
 	// shortcut common case of //-style comments
diff --git a/libgo/go/go/printer/printer_test.go b/libgo/go/go/printer/printer_test.go
index 5984d2c4d24..27d46df6b18 100644
--- a/libgo/go/go/printer/printer_test.go
+++ b/libgo/go/go/printer/printer_test.go
@@ -188,12 +188,14 @@ var data = []entry{
 	{"comments.input", "comments.golden", 0},
 	{"comments.input", "comments.x", export},
 	{"comments2.input", "comments2.golden", idempotent},
+	{"alignment.input", "alignment.golden", idempotent},
 	{"linebreaks.input", "linebreaks.golden", idempotent},
 	{"expressions.input", "expressions.golden", idempotent},
 	{"expressions.input", "expressions.raw", rawFormat | idempotent},
 	{"declarations.input", "declarations.golden", 0},
 	{"statements.input", "statements.golden", 0},
 	{"slow.input", "slow.golden", idempotent},
+	{"complit.input", "complit.x", export},
 }
 
 func TestFiles(t *testing.T) {
@@ -325,7 +327,7 @@ func fibo(n int) {
 
 	comment := f.Comments[0].List[0]
 	pos := comment.Pos()
-	if fset.Position(pos).Offset != 1 {
+	if fset.PositionFor(pos, false /* absolute position */).Offset != 1 {
 		t.Error("expected offset 1") // error in test
 	}
 
@@ -422,6 +424,7 @@ func (t *t) foo(a, b, c int) int {
 			t.Errorf("got ident %s; want %s", i2.Name, i1.Name)
 		}
 
+		// here we care about the relative (line-directive adjusted) positions
 		l1 := fset.Position(i1.Pos()).Line
 		l2 := fset.Position(i2.Pos()).Line
 		if l2 != l1 {
@@ -710,3 +713,26 @@ type bar int	// comment2
 		t.Errorf("got %q, want %q", buf.String(), bar)
 	}
 }
+
+func TestIssue11151(t *testing.T) {
+	const src = "package p\t/*\r/1\r*\r/2*\r\r\r\r/3*\r\r+\r\r/4*/\n"
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var buf bytes.Buffer
+	Fprint(&buf, fset, f)
+	got := buf.String()
+	const want = "package p\t/*/1*\r/2*\r/3*+/4*/\n" // \r following opening /* should be stripped
+	if got != want {
+		t.Errorf("\ngot : %q\nwant: %q", got, want)
+	}
+
+	// the resulting program must be valid
+	_, err = parser.ParseFile(fset, "", got, 0)
+	if err != nil {
+		t.Errorf("%v\norig: %q\ngot : %q", err, src, got)
+	}
+}
diff --git a/libgo/go/go/printer/testdata/alignment.golden b/libgo/go/go/printer/testdata/alignment.golden
new file mode 100644
index 00000000000..96086ed9068
--- /dev/null
+++ b/libgo/go/go/printer/testdata/alignment.golden
@@ -0,0 +1,172 @@
+// 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 alignment
+
+// ----------------------------------------------------------------------------
+// Examples from issue #7335.
+
+func main() {
+	z := MyStruct{
+		Foo:		"foo",
+		Bar:		"bar",
+		Name:		"name",
+		LongName:	"longname",
+		Baz:		"baz",
+	}
+	y := MyStruct{
+		Foo:			"foo",
+		Bar:			"bar",
+		NameXX:			"name",
+		LongNameXXXXXXXXXXXXX:	"longname",
+		Baz:			"baz",
+	}
+	z := MyStruct{
+		Foo:			"foo",
+		Bar:			"bar",
+		Name:			"name",
+		LongNameXXXXXXXXXXXXX:	"longname",
+		Baz:			"baz",
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Examples from issue #10392.
+
+var kcfg = KubeletConfig{
+	Address:			s.Address,
+	AllowPrivileged:		s.AllowPrivileged,
+	HostNetworkSources:		hostNetworkSources,
+	HostnameOverride:		s.HostnameOverride,
+	RootDirectory:			s.RootDirectory,
+	ConfigFile:			s.Config,
+	ManifestURL:			s.ManifestURL,
+	FileCheckFrequency:		s.FileCheckFrequency,
+	HTTPCheckFrequency:		s.HTTPCheckFrequency,
+	PodInfraContainerImage:		s.PodInfraContainerImage,
+	SyncFrequency:			s.SyncFrequency,
+	RegistryPullQPS:		s.RegistryPullQPS,
+	RegistryBurst:			s.RegistryBurst,
+	MinimumGCAge:			s.MinimumGCAge,
+	MaxPerPodContainerCount:	s.MaxPerPodContainerCount,
+	MaxContainerCount:		s.MaxContainerCount,
+	ClusterDomain:			s.ClusterDomain,
+	ClusterDNS:			s.ClusterDNS,
+	Runonce:			s.RunOnce,
+	Port:				s.Port,
+	ReadOnlyPort:			s.ReadOnlyPort,
+	CadvisorInterface:		cadvisorInterface,
+	EnableServer:			s.EnableServer,
+	EnableDebuggingHandlers:	s.EnableDebuggingHandlers,
+	DockerClient:			dockertools.ConnectToDockerOrDie(s.DockerEndpoint),
+	KubeClient:			client,
+	MasterServiceNamespace:		s.MasterServiceNamespace,
+	VolumePlugins:			ProbeVolumePlugins(),
+	NetworkPlugins:			ProbeNetworkPlugins(),
+	NetworkPluginName:		s.NetworkPluginName,
+	StreamingConnectionIdleTimeout:	s.StreamingConnectionIdleTimeout,
+	TLSOptions:			tlsOptions,
+	ImageGCPolicy:			imageGCPolicy, imageGCPolicy,
+	Cloud:				cloud,
+	NodeStatusUpdateFrequency:	s.NodeStatusUpdateFrequency,
+}
+
+var a = A{
+	Long:					1,
+	LongLong:				1,
+	LongLongLong:				1,
+	LongLongLongLong:			1,
+	LongLongLongLongLong:			1,
+	LongLongLongLongLongLong:		1,
+	LongLongLongLongLongLongLong:		1,
+	LongLongLongLongLongLongLongLong:	1,
+	Short:					1,
+	LongLongLongLongLongLongLongLongLong:	3,
+}
+
+// ----------------------------------------------------------------------------
+// Examples from issue #22852.
+
+var fmtMap = map[string]string{
+	"1":					"123",
+	"12":					"123",
+	"123":					"123",
+	"1234":					"123",
+	"12345":				"123",
+	"123456":				"123",
+	"12345678901234567890123456789":	"123",
+	"abcde":				"123",
+	"123456789012345678901234567890":	"123",
+	"1234567":				"123",
+	"abcdefghijklmnopqrstuvwxyzabcd":	"123",
+	"abcd":					"123",
+}
+
+type Fmt struct {
+	abcdefghijklmnopqrstuvwx	string
+	abcdefghijklmnopqrstuvwxy	string
+	abcdefghijklmnopqrstuvwxyz	string
+	abcdefghijklmnopqrstuvwxyza	string
+	abcdefghijklmnopqrstuvwxyzab	string
+	abcdefghijklmnopqrstuvwxyzabc	string
+	abcde				string
+	abcdefghijklmnopqrstuvwxyzabcde	string
+	abcdefg				string
+}
+
+func main() {
+	_ := Fmt{
+		abcdefghijklmnopqrstuvwx:		"foo",
+		abcdefghijklmnopqrstuvwxyza:		"foo",
+		abcdefghijklmnopqrstuvwxyzab:		"foo",
+		abcdefghijklmnopqrstuvwxyzabc:		"foo",
+		abcde:					"foo",
+		abcdefghijklmnopqrstuvwxyzabcde:	"foo",
+		abcdefg:				"foo",
+		abcdefghijklmnopqrstuvwxy:		"foo",
+		abcdefghijklmnopqrstuvwxyz:		"foo",
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Examples from issue #26352.
+
+var _ = map[int]string{
+	1:	"",
+
+	12345678901234567890123456789:		"",
+	12345678901234567890123456789012345678:	"",
+}
+
+func f() {
+	_ = map[int]string{
+		1:	"",
+
+		12345678901234567:				"",
+		12345678901234567890123456789012345678901:	"",
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Examples from issue #26930.
+
+var _ = S{
+	F1:	[]string{},
+	F2____:	[]string{},
+}
+
+var _ = S{
+	F1:	[]string{},
+	F2____:	[]string{},
+}
+
+var _ = S{
+	F1____:	[]string{},
+	F2:	[]string{},
+}
+
+var _ = S{
+	F1____:	[]string{},
+	F2:	[]string{},
+}
diff --git a/libgo/go/go/printer/testdata/alignment.input b/libgo/go/go/printer/testdata/alignment.input
new file mode 100644
index 00000000000..323d2689e0b
--- /dev/null
+++ b/libgo/go/go/printer/testdata/alignment.input
@@ -0,0 +1,179 @@
+// 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 alignment
+
+// ----------------------------------------------------------------------------
+// Examples from issue #7335.
+
+func main() {
+    z := MyStruct{
+        Foo:      "foo",
+        Bar:      "bar",
+        Name:     "name",
+        LongName: "longname",
+        Baz:      "baz",
+    }
+    y := MyStruct{
+        Foo:                   "foo",
+        Bar:                   "bar",
+        NameXX:                "name",
+        LongNameXXXXXXXXXXXXX: "longname",
+        Baz: "baz",
+    }
+    z := MyStruct{
+        Foo:  "foo",
+        Bar:  "bar",
+        Name: "name",
+        LongNameXXXXXXXXXXXXX: "longname",
+        Baz: "baz",
+    }
+}
+
+// ----------------------------------------------------------------------------
+// Examples from issue #10392.
+
+var kcfg = KubeletConfig{
+    Address:                        s.Address,
+    AllowPrivileged:                s.AllowPrivileged,
+    HostNetworkSources:             hostNetworkSources,
+    HostnameOverride:               s.HostnameOverride,
+    RootDirectory:                  s.RootDirectory,
+    ConfigFile:                     s.Config,
+    ManifestURL:                    s.ManifestURL,
+    FileCheckFrequency:             s.FileCheckFrequency,
+    HTTPCheckFrequency:             s.HTTPCheckFrequency,
+    PodInfraContainerImage:         s.PodInfraContainerImage,
+    SyncFrequency:                  s.SyncFrequency,
+    RegistryPullQPS:                s.RegistryPullQPS,
+    RegistryBurst:                  s.RegistryBurst,
+    MinimumGCAge:                   s.MinimumGCAge,
+    MaxPerPodContainerCount:        s.MaxPerPodContainerCount,
+    MaxContainerCount:              s.MaxContainerCount,
+    ClusterDomain:                  s.ClusterDomain,
+    ClusterDNS:                     s.ClusterDNS,
+    Runonce:                        s.RunOnce,
+    Port:                           s.Port,
+    ReadOnlyPort:                   s.ReadOnlyPort,
+    CadvisorInterface:              cadvisorInterface,
+    EnableServer:                   s.EnableServer,
+    EnableDebuggingHandlers:        s.EnableDebuggingHandlers,
+    DockerClient:                   dockertools.ConnectToDockerOrDie(s.DockerEndpoint),
+    KubeClient:                     client,
+    MasterServiceNamespace:         s.MasterServiceNamespace,
+    VolumePlugins:                  ProbeVolumePlugins(),
+    NetworkPlugins:                 ProbeNetworkPlugins(),
+    NetworkPluginName:              s.NetworkPluginName,
+    StreamingConnectionIdleTimeout: s.StreamingConnectionIdleTimeout,
+    TLSOptions:                     tlsOptions,
+    ImageGCPolicy:                  imageGCPolicy,imageGCPolicy,
+    Cloud:                          cloud,
+    NodeStatusUpdateFrequency: s.NodeStatusUpdateFrequency,
+}
+
+var a = A{
+    Long:                             1,
+    LongLong:                         1,
+    LongLongLong:                     1,
+    LongLongLongLong:                 1,
+    LongLongLongLongLong:             1,
+    LongLongLongLongLongLong:         1,
+    LongLongLongLongLongLongLong:     1,
+    LongLongLongLongLongLongLongLong: 1,
+    Short: 1,
+    LongLongLongLongLongLongLongLongLong: 3,
+}
+
+// ----------------------------------------------------------------------------
+// Examples from issue #22852.
+
+var fmtMap = map[string]string{
+	"1": "123",
+	"12": "123",
+	"123": "123",
+	"1234": "123",
+	"12345": "123",
+	"123456": "123",
+	"12345678901234567890123456789": "123",
+	"abcde": "123",
+	"123456789012345678901234567890": "123",
+	"1234567": "123",
+	"abcdefghijklmnopqrstuvwxyzabcd": "123",
+	"abcd": "123",
+}
+
+type Fmt struct {
+	abcdefghijklmnopqrstuvwx string
+	abcdefghijklmnopqrstuvwxy string
+	abcdefghijklmnopqrstuvwxyz string
+	abcdefghijklmnopqrstuvwxyza string
+	abcdefghijklmnopqrstuvwxyzab string
+	abcdefghijklmnopqrstuvwxyzabc string
+	abcde string
+	abcdefghijklmnopqrstuvwxyzabcde string
+	abcdefg string
+}
+
+func main() {
+	_ := Fmt{
+		abcdefghijklmnopqrstuvwx: "foo",
+		abcdefghijklmnopqrstuvwxyza: "foo",
+		abcdefghijklmnopqrstuvwxyzab: "foo",
+		abcdefghijklmnopqrstuvwxyzabc: "foo",
+		abcde: "foo",
+		abcdefghijklmnopqrstuvwxyzabcde: "foo",
+		abcdefg: "foo",
+		abcdefghijklmnopqrstuvwxy: "foo",
+		abcdefghijklmnopqrstuvwxyz: "foo",
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Examples from issue #26352.
+
+var _ = map[int]string{
+	1: "",
+
+	12345678901234567890123456789: "",
+	12345678901234567890123456789012345678: "",
+}
+
+func f() {
+	_ = map[int]string{
+		1: "",
+
+		12345678901234567: "",
+		12345678901234567890123456789012345678901: "",
+	}
+}
+
+// ----------------------------------------------------------------------------
+// Examples from issue #26930.
+
+var _ = S{
+	F1: []string{
+	},
+	F2____: []string{},
+}
+
+var _ = S{
+	F1: []string{
+
+
+	},
+	F2____: []string{},
+}
+
+var _ = S{
+	F1____: []string{
+	},
+	F2: []string{},
+}
+
+var _ = S{
+	F1____: []string{
+
+	},
+	F2: []string{},
+}
diff --git a/libgo/go/go/printer/testdata/comments.golden b/libgo/go/go/printer/testdata/comments.golden
index e1818e5fd53..1a21fff3314 100644
--- a/libgo/go/go/printer/testdata/comments.golden
+++ b/libgo/go/go/printer/testdata/comments.golden
@@ -702,8 +702,8 @@ func _() {
 	//line foo:2
 	_ = 2
 
-	// The following is not a legal line directive (negative line number):
-	//line foo:-3
+	// The following is not a legal line directive (missing colon):
+//line foo -3
 	_ = 3
 }
 
diff --git a/libgo/go/go/printer/testdata/comments.input b/libgo/go/go/printer/testdata/comments.input
index f3eda12c229..aa428a2aa68 100644
--- a/libgo/go/go/printer/testdata/comments.input
+++ b/libgo/go/go/printer/testdata/comments.input
@@ -699,8 +699,8 @@ func _() {
 	//line foo:2
 	_ = 2
 
-// The following is not a legal line directive (negative line number):
-//line foo:-3
+// The following is not a legal line directive (missing colon):
+//line foo -3
 	_ = 3
 }
 
diff --git a/libgo/go/go/printer/testdata/complit.input b/libgo/go/go/printer/testdata/complit.input
new file mode 100644
index 00000000000..82806a4233d
--- /dev/null
+++ b/libgo/go/go/printer/testdata/complit.input
@@ -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.
+
+package complit
+
+var (
+	// Multi-line declarations
+	V1 = T{
+		F1: "hello",
+		f2: 1,
+	}
+	V2 = T{
+		f2: 1,
+		F1: "hello",
+	}
+	V3 = T{
+		F1: "hello",
+		F2: T2{
+			A: "world",
+			b: "hidden",
+		},
+		f3: T2{
+			A: "world",
+		},
+	}
+	V4 = T{
+		f2: 1,
+	}
+
+	// Single-line declarations
+	V5 = T{F1: "hello", f2: 1}
+	V6 = T{f2: 1, F1: "hello"}
+	V7 = T{f2: 1}
+
+	// Mixed-mode declarations
+	V8 = T{
+		F1: "hello", f2: 1,
+		F3: "world",
+		f4: 2}
+	V9 = T{
+	f2: 1, F1: "hello",}
+	V10 = T{
+		F1: "hello", f2: 1,
+		f3: 2,
+		F4: "world", f5: 3,
+	}
+
+	// Other miscellaneous declarations
+	V11 = T{
+		t{
+			A: "world",
+			b: "hidden",
+		},
+		f2: t{
+			A: "world",
+			b: "hidden",
+		},
+	}
+	V12 = T{
+		F1: make(chan int),
+		f2: []int{},
+		F3: make(map[int]string), f4: 1,
+	}
+)
\ No newline at end of file
diff --git a/libgo/go/go/printer/testdata/complit.x b/libgo/go/go/printer/testdata/complit.x
new file mode 100644
index 00000000000..458ac6117a7
--- /dev/null
+++ b/libgo/go/go/printer/testdata/complit.x
@@ -0,0 +1,62 @@
+package complit
+
+var (
+	// Multi-line declarations
+	V1	= T{
+		F1: "hello",
+		// contains filtered or unexported fields
+	}
+	V2	= T{
+
+		F1: "hello",
+		// contains filtered or unexported fields
+	}
+	V3	= T{
+		F1:	"hello",
+		F2: T2{
+			A: "world",
+			// contains filtered or unexported fields
+		},
+		// contains filtered or unexported fields
+	}
+	V4	= T{
+		// contains filtered or unexported fields
+	}
+
+	// Single-line declarations
+	V5	= T{F1: "hello", /* contains filtered or unexported fields */}
+	V6	= T{F1: "hello", /* contains filtered or unexported fields */}
+	V7	= T{/* contains filtered or unexported fields */}
+
+	// Mixed-mode declarations
+	V8	= T{
+		F1:	"hello",
+		F3:	"world",
+		// contains filtered or unexported fields
+	}
+	V9	= T{
+		F1: "hello",
+		// contains filtered or unexported fields
+	}
+	V10	= T{
+		F1:	"hello",
+
+		F4:	"world",
+		// contains filtered or unexported fields
+	}
+
+	// Other miscellaneous declarations
+	V11	= T{
+		t{
+			A: "world",
+			// contains filtered or unexported fields
+		},
+		// contains filtered or unexported fields
+	}
+	V12	= T{
+		F1:	make(chan int),
+
+		F3:	make(map[int]string),
+		// contains filtered or unexported fields
+	}
+)
diff --git a/libgo/go/go/printer/testdata/declarations.golden b/libgo/go/go/printer/testdata/declarations.golden
index bebc0eaa637..fe0f7838de5 100644
--- a/libgo/go/go/printer/testdata/declarations.golden
+++ b/libgo/go/go/printer/testdata/declarations.golden
@@ -688,8 +688,8 @@ var _ = T1{
 
 // not aligned
 var _ = T2{
-	a:	x,
-	b:	y,
+	a:			x,
+	b:			y,
 	ccccccccccccccccccccc:	z,
 }
 
@@ -703,8 +703,8 @@ var _ = T3{
 // not aligned
 var _ = T4{
 	aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:	x,
-	b:	y,
-	c:	z,
+	b:						y,
+	c:						z,
 }
 
 // no alignment of map composite entries if they are not the first entry on a line
diff --git a/libgo/go/go/printer/testdata/linebreaks.golden b/libgo/go/go/printer/testdata/linebreaks.golden
index 006cf171848..17d2b5cc50c 100644
--- a/libgo/go/go/printer/testdata/linebreaks.golden
+++ b/libgo/go/go/printer/testdata/linebreaks.golden
@@ -256,7 +256,7 @@ func _(
 ) {
 }
 
-// Example from issue 2597.
+// Example from issue #2597.
 func ManageStatus0(
 	in <-chan *Status,
 	req <-chan Request,
@@ -272,4 +272,24 @@ func ManageStatus1(
 ) {
 }
 
+// Example from issue #9064.
+func (y *y) xerrors() error {
+	_ = "xerror.test"	//TODO-
+	_ = []byte(`
+foo bar foo bar foo bar
+`) //TODO-
+}
+
+func _() {
+	_ = "abc"		// foo
+	_ = `abc_0123456789_`	// foo
+}
+
+func _() {
+	_ = "abc"	// foo
+	_ = `abc
+0123456789
+` // foo
+}
+
 // There should be exactly one linebreak after this comment.
diff --git a/libgo/go/go/printer/testdata/linebreaks.input b/libgo/go/go/printer/testdata/linebreaks.input
index e782bb04443..9e714f3eff4 100644
--- a/libgo/go/go/printer/testdata/linebreaks.input
+++ b/libgo/go/go/printer/testdata/linebreaks.input
@@ -252,7 +252,7 @@ func _(
        y T,
 ) {}
 
-// Example from issue 2597.
+// Example from issue #2597.
 func ManageStatus0(
 	in <-chan *Status,
 	req <-chan Request,
@@ -267,5 +267,25 @@ func ManageStatus1(
 	TargetHistorySize int,
 ) {
 }
-    
+
+// Example from issue #9064.
+func (y *y) xerrors() error {
+	_ = "xerror.test" //TODO-
+	_ = []byte(`
+foo bar foo bar foo bar
+`) //TODO-
+}
+
+func _() {
+	_ = "abc" // foo
+	_ = `abc_0123456789_` // foo
+}
+
+func _() {
+	_ = "abc" // foo
+	_ = `abc
+0123456789
+` // foo
+}
+
 // There should be exactly one linebreak after this comment.
diff --git a/libgo/go/go/scanner/scanner.go b/libgo/go/go/scanner/scanner.go
index a86e4eb668c..23bbb2885fb 100644
--- a/libgo/go/go/scanner/scanner.go
+++ b/libgo/go/go/scanner/scanner.go
@@ -141,46 +141,26 @@ func (s *Scanner) error(offs int, msg string) {
 	s.ErrorCount++
 }
 
-var prefix = []byte("//line ")
-
-func (s *Scanner) interpretLineComment(text []byte) {
-	if bytes.HasPrefix(text, prefix) {
-		// get filename and line number, if any
-		if i := bytes.LastIndex(text, []byte{':'}); i > 0 {
-			if line, err := strconv.Atoi(string(text[i+1:])); err == nil && line > 0 {
-				// valid //line filename:line comment
-				filename := string(bytes.TrimSpace(text[len(prefix):i]))
-				if filename != "" {
-					filename = filepath.Clean(filename)
-					if !filepath.IsAbs(filename) {
-						// make filename relative to current directory
-						filename = filepath.Join(s.dir, filename)
-					}
-				}
-				// update scanner position
-				s.file.AddLineInfo(s.lineOffset+len(text)+1, filename, line) // +len(text)+1 since comment applies to next line
-			}
-		}
-	}
-}
-
 func (s *Scanner) scanComment() string {
 	// initial '/' already consumed; s.ch == '/' || s.ch == '*'
 	offs := s.offset - 1 // position of initial '/'
-	hasCR := false
+	next := -1           // position immediately following the comment; < 0 means invalid comment
+	numCR := 0
 
 	if s.ch == '/' {
 		//-style comment
+		// (the final '\n' is not considered part of the comment)
 		s.next()
 		for s.ch != '\n' && s.ch >= 0 {
 			if s.ch == '\r' {
-				hasCR = true
+				numCR++
 			}
 			s.next()
 		}
-		if offs == s.lineOffset {
-			// comment starts at the beginning of the current line
-			s.interpretLineComment(s.src[offs:s.offset])
+		// if we are at '\n', the position following the comment is afterwards
+		next = s.offset
+		if s.ch == '\n' {
+			next++
 		}
 		goto exit
 	}
@@ -190,11 +170,12 @@ func (s *Scanner) scanComment() string {
 	for s.ch >= 0 {
 		ch := s.ch
 		if ch == '\r' {
-			hasCR = true
+			numCR++
 		}
 		s.next()
 		if ch == '*' && s.ch == '/' {
 			s.next()
+			next = s.offset
 			goto exit
 		}
 	}
@@ -203,13 +184,104 @@ func (s *Scanner) scanComment() string {
 
 exit:
 	lit := s.src[offs:s.offset]
-	if hasCR {
-		lit = stripCR(lit)
+
+	// On Windows, a (//-comment) line may end in "\r\n".
+	// Remove the final '\r' before analyzing the text for
+	// line directives (matching the compiler). Remove any
+	// other '\r' afterwards (matching the pre-existing be-
+	// havior of the scanner).
+	if numCR > 0 && len(lit) >= 2 && lit[1] == '/' && lit[len(lit)-1] == '\r' {
+		lit = lit[:len(lit)-1]
+		numCR--
+	}
+
+	// interpret line directives
+	// (//line directives must start at the beginning of the current line)
+	if next >= 0 /* implies valid comment */ && (lit[1] == '*' || offs == s.lineOffset) && bytes.HasPrefix(lit[2:], prefix) {
+		s.updateLineInfo(next, offs, lit)
+	}
+
+	if numCR > 0 {
+		lit = stripCR(lit, lit[1] == '*')
 	}
 
 	return string(lit)
 }
 
+var prefix = []byte("line ")
+
+// updateLineInfo parses the incoming comment text at offset offs
+// as a line directive. If successful, it updates the line info table
+// for the position next per the line directive.
+func (s *Scanner) updateLineInfo(next, offs int, text []byte) {
+	// extract comment text
+	if text[1] == '*' {
+		text = text[:len(text)-2] // lop off trailing "*/"
+	}
+	text = text[7:] // lop off leading "//line " or "/*line "
+	offs += 7
+
+	i, n, ok := trailingDigits(text)
+	if i == 0 {
+		return // ignore (not a line directive)
+	}
+	// i > 0
+
+	if !ok {
+		// text has a suffix :xxx but xxx is not a number
+		s.error(offs+i, "invalid line number: "+string(text[i:]))
+		return
+	}
+
+	var line, col int
+	i2, n2, ok2 := trailingDigits(text[:i-1])
+	if ok2 {
+		//line filename:line:col
+		i, i2 = i2, i
+		line, col = n2, n
+		if col == 0 {
+			s.error(offs+i2, "invalid column number: "+string(text[i2:]))
+			return
+		}
+		text = text[:i2-1] // lop off ":col"
+	} else {
+		//line filename:line
+		line = n
+	}
+
+	if line == 0 {
+		s.error(offs+i, "invalid line number: "+string(text[i:]))
+		return
+	}
+
+	// If we have a column (//line filename:line:col form),
+	// an empty filename means to use the previous filename.
+	filename := string(text[:i-1]) // lop off ":line", and trim white space
+	if filename == "" && ok2 {
+		filename = s.file.Position(s.file.Pos(offs)).Filename
+	} else if filename != "" {
+		// Put a relative filename in the current directory.
+		// This is for compatibility with earlier releases.
+		// See issue 26671.
+		filename = filepath.Clean(filename)
+		if !filepath.IsAbs(filename) {
+			filename = filepath.Join(s.dir, filename)
+		}
+	}
+
+	s.file.AddLineColumnInfo(next, filename, line, col)
+}
+
+func trailingDigits(text []byte) (int, int, bool) {
+	i := bytes.LastIndexByte(text, ':') // look from right (Windows filenames may contain ':')
+	if i < 0 {
+		return 0, 0, false // no ":"
+	}
+	// i >= 0
+	n, err := strconv.ParseUint(string(text[i+1:]), 10, 0)
+	return i + 1, int(n), err == nil
+}
+
 func (s *Scanner) findLineEnd() bool {
 	// initial '/' already consumed
 
@@ -480,11 +552,16 @@ func (s *Scanner) scanString() string {
 	return string(s.src[offs:s.offset])
 }
 
-func stripCR(b []byte) []byte {
+func stripCR(b []byte, comment bool) []byte {
 	c := make([]byte, len(b))
 	i := 0
-	for _, ch := range b {
-		if ch != '\r' {
+	for j, ch := range b {
+		// In a /*-style comment, don't strip \r from *\r/ (incl.
+		// sequences of \r from *\r\r...\r/) since the resulting
+		// */ would terminate the comment too early unless the \r
+		// is immediately following the opening /* in which case
+		// it's ok because /*/ is not closed yet (issue #11151).
+		if ch != '\r' || comment && i > len("/*") && c[i-1] == '*' && j+1 < len(b) && b[j+1] == '/' {
 			c[i] = ch
 			i++
 		}
@@ -514,7 +591,7 @@ func (s *Scanner) scanRawString() string {
 
 	lit := s.src[offs:s.offset]
 	if hasCR {
-		lit = stripCR(lit)
+		lit = stripCR(lit, false)
 	}
 
 	return string(lit)
diff --git a/libgo/go/go/scanner/scanner_test.go b/libgo/go/go/scanner/scanner_test.go
index ff41c036f00..0aad3680990 100644
--- a/libgo/go/go/scanner/scanner_test.go
+++ b/libgo/go/go/scanner/scanner_test.go
@@ -45,6 +45,8 @@ var tokens = [...]elt{
 	{token.COMMENT, "/* a comment */", special},
 	{token.COMMENT, "// a comment \n", special},
 	{token.COMMENT, "/*\r*/", special},
+	{token.COMMENT, "/**\r/*/", special}, // issue 11151
+	{token.COMMENT, "/**\r\r/*/", special},
 	{token.COMMENT, "//\r\n", special},
 
 	// Identifiers and basic type literals
@@ -203,7 +205,9 @@ func newlineCount(s string) int {
 
 func checkPos(t *testing.T, lit string, p token.Pos, expected token.Position) {
 	pos := fset.Position(p)
-	if pos.Filename != expected.Filename {
+	// Check cleaned filenames so that we don't have to worry about
+	// different os.PathSeparator values.
+	if pos.Filename != expected.Filename && filepath.Clean(pos.Filename) != filepath.Clean(expected.Filename) {
 		t.Errorf("bad filename for %q: got %s, expected %s", lit, pos.Filename, expected.Filename)
 	}
 	if pos.Offset != expected.Offset {
@@ -270,7 +274,7 @@ func TestScan(t *testing.T) {
 		switch e.tok {
 		case token.COMMENT:
 			// no CRs in comments
-			elit = string(stripCR([]byte(e.lit)))
+			elit = string(stripCR([]byte(e.lit), e.lit[1] == '*'))
 			//-style comment literal doesn't contain newline
 			if elit[1] == '/' {
 				elit = elit[0 : len(elit)-1]
@@ -284,7 +288,7 @@ func TestScan(t *testing.T) {
 				// no CRs in raw string literals
 				elit = e.lit
 				if elit[0] == '`' {
-					elit = string(stripCR([]byte(elit)))
+					elit = string(stripCR([]byte(elit), false))
 				}
 			} else if e.tok.IsKeyword() {
 				elit = e.lit
@@ -309,6 +313,26 @@ func TestScan(t *testing.T) {
 	}
 }
 
+func TestStripCR(t *testing.T) {
+	for _, test := range []struct{ have, want string }{
+		{"//\n", "//\n"},
+		{"//\r\n", "//\n"},
+		{"//\r\r\r\n", "//\n"},
+		{"//\r*\r/\r\n", "//*/\n"},
+		{"/**/", "/**/"},
+		{"/*\r/*/", "/*/*/"},
+		{"/*\r*/", "/**/"},
+		{"/**\r/*/", "/**\r/*/"},
+		{"/*\r/\r*\r/*/", "/*/*\r/*/"},
+		{"/*\r\r\r\r*/", "/**/"},
+	} {
+		got := string(stripCR([]byte(test.have), len(test.have) >= 2 && test.have[1] == '*'))
+		if got != test.want {
+			t.Errorf("stripCR(%q) = %q; want %q", test.have, got, test.want)
+		}
+	}
+}
+
 func checkSemi(t *testing.T, line string, mode Mode) {
 	var S Scanner
 	file := fset.AddFile("TestSemis", fset.Base(), len(line))
@@ -481,69 +505,130 @@ func TestSemis(t *testing.T) {
 }
 
 type segment struct {
-	srcline  string // a line of source text
-	filename string // filename for current token
-	line     int    // line number for current token
+	srcline      string // a line of source text
+	filename     string // filename for current token; error message for invalid line directives
+	line, column int    // line and column for current token; error position for invalid line directives
 }
 
 var segments = []segment{
 	// exactly one token per line since the test consumes one token per segment
-	{"  line1", filepath.Join("dir", "TestLineComments"), 1},
-	{"\nline2", filepath.Join("dir", "TestLineComments"), 2},
-	{"\nline3  //line File1.go:100", filepath.Join("dir", "TestLineComments"), 3}, // bad line comment, ignored
-	{"\nline4", filepath.Join("dir", "TestLineComments"), 4},
-	{"\n//line File1.go:100\n  line100", filepath.Join("dir", "File1.go"), 100},
-	{"\n//line  \t :42\n  line1", "", 42},
-	{"\n//line File2.go:200\n  line200", filepath.Join("dir", "File2.go"), 200},
-	{"\n//line foo\t:42\n  line42", filepath.Join("dir", "foo"), 42},
-	{"\n //line foo:42\n  line44", filepath.Join("dir", "foo"), 44},           // bad line comment, ignored
-	{"\n//line foo 42\n  line46", filepath.Join("dir", "foo"), 46},            // bad line comment, ignored
-	{"\n//line foo:42 extra text\n  line48", filepath.Join("dir", "foo"), 48}, // bad line comment, ignored
-	{"\n//line ./foo:42\n  line42", filepath.Join("dir", "foo"), 42},
-	{"\n//line a/b/c/File1.go:100\n  line100", filepath.Join("dir", "a", "b", "c", "File1.go"), 100},
+	{"  line1", "TestLineDirectives", 1, 3},
+	{"\nline2", "TestLineDirectives", 2, 1},
+	{"\nline3  //line File1.go:100", "TestLineDirectives", 3, 1}, // bad line comment, ignored
+	{"\nline4", "TestLineDirectives", 4, 1},
+	{"\n//line File1.go:100\n  line100", "File1.go", 100, 0},
+	{"\n//line  \t :42\n  line1", " \t ", 42, 0},
+	{"\n//line File2.go:200\n  line200", "File2.go", 200, 0},
+	{"\n//line foo\t:42\n  line42", "foo\t", 42, 0},
+	{"\n //line foo:42\n  line43", "foo\t", 44, 0}, // bad line comment, ignored (use existing, prior filename)
+	{"\n//line foo 42\n  line44", "foo\t", 46, 0},  // bad line comment, ignored (use existing, prior filename)
+	{"\n//line /bar:42\n  line45", "/bar", 42, 0},
+	{"\n//line ./foo:42\n  line46", "foo", 42, 0},
+	{"\n//line a/b/c/File1.go:100\n  line100", "a/b/c/File1.go", 100, 0},
+	{"\n//line c:\\bar:42\n  line200", "c:\\bar", 42, 0},
+	{"\n//line c:\\dir\\File1.go:100\n  line201", "c:\\dir\\File1.go", 100, 0},
+
+	// tests for new line directive syntax
+	{"\n//line :100\na1", "", 100, 0}, // missing filename means empty filename
+	{"\n//line bar:100\nb1", "bar", 100, 0},
+	{"\n//line :100:10\nc1", "bar", 100, 10}, // missing filename means current filename
+	{"\n//line foo:100:10\nd1", "foo", 100, 10},
+
+	{"\n/*line :100*/a2", "", 100, 0}, // missing filename means empty filename
+	{"\n/*line bar:100*/b2", "bar", 100, 0},
+	{"\n/*line :100:10*/c2", "bar", 100, 10}, // missing filename means current filename
+	{"\n/*line foo:100:10*/d2", "foo", 100, 10},
+	{"\n/*line foo:100:10*/    e2", "foo", 100, 14}, // line-directive relative column
+	{"\n/*line foo:100:10*/\n\nf2", "foo", 102, 1},  // absolute column since on new line
 }
 
-var unixsegments = []segment{
-	{"\n//line /bar:42\n  line42", "/bar", 42},
+var dirsegments = []segment{
+	// exactly one token per line since the test consumes one token per segment
+	{"  line1", "TestLineDir/TestLineDirectives", 1, 3},
+	{"\n//line File1.go:100\n  line100", "TestLineDir/File1.go", 100, 0},
 }
 
-var winsegments = []segment{
-	{"\n//line c:\\bar:42\n  line42", "c:\\bar", 42},
-	{"\n//line c:\\dir\\File1.go:100\n  line100", "c:\\dir\\File1.go", 100},
+var dirUnixSegments = []segment{
+	{"\n//line /bar:42\n  line42", "/bar", 42, 0},
 }
 
-// Verify that comments of the form "//line filename:line" are interpreted correctly.
-func TestLineComments(t *testing.T) {
-	segs := segments
+var dirWindowsSegments = []segment{
+	{"\n//line c:\\bar:42\n  line42", "c:\\bar", 42, 0},
+}
+
+// Verify that line directives are interpreted correctly.
+func TestLineDirectives(t *testing.T) {
+	testSegments(t, segments, "TestLineDirectives")
+	testSegments(t, dirsegments, "TestLineDir/TestLineDirectives")
 	if runtime.GOOS == "windows" {
-		segs = append(segs, winsegments...)
+		testSegments(t, dirWindowsSegments, "TestLineDir/TestLineDirectives")
 	} else {
-		segs = append(segs, unixsegments...)
+		testSegments(t, dirUnixSegments, "TestLineDir/TestLineDirectives")
 	}
+}
 
-	// make source
+func testSegments(t *testing.T, segments []segment, filename string) {
 	var src string
-	for _, e := range segs {
+	for _, e := range segments {
 		src += e.srcline
 	}
 
 	// verify scan
 	var S Scanner
-	file := fset.AddFile(filepath.Join("dir", "TestLineComments"), fset.Base(), len(src))
-	S.Init(file, []byte(src), nil, dontInsertSemis)
-	for _, s := range segs {
+	file := fset.AddFile(filename, fset.Base(), len(src))
+	S.Init(file, []byte(src), func(pos token.Position, msg string) { t.Error(Error{pos, msg}) }, dontInsertSemis)
+	for _, s := range segments {
 		p, _, lit := S.Scan()
 		pos := file.Position(p)
 		checkPos(t, lit, p, token.Position{
 			Filename: s.filename,
 			Offset:   pos.Offset,
 			Line:     s.line,
-			Column:   pos.Column,
+			Column:   s.column,
 		})
 	}
 
 	if S.ErrorCount != 0 {
-		t.Errorf("found %d errors", S.ErrorCount)
+		t.Errorf("got %d errors", S.ErrorCount)
+	}
+}
+
+// The filename is used for the error message in these test cases.
+// The first line directive is valid and used to control the expected error line.
+var invalidSegments = []segment{
+	{"\n//line :1:1\n//line foo:42 extra text\ndummy", "invalid line number: 42 extra text", 1, 12},
+	{"\n//line :2:1\n//line foobar:\ndummy", "invalid line number: ", 2, 15},
+	{"\n//line :5:1\n//line :0\ndummy", "invalid line number: 0", 5, 9},
+	{"\n//line :10:1\n//line :1:0\ndummy", "invalid column number: 0", 10, 11},
+	{"\n//line :1:1\n//line :foo:0\ndummy", "invalid line number: 0", 1, 13}, // foo is considered part of the filename
+}
+
+// Verify that invalid line directives get the correct error message.
+func TestInvalidLineDirectives(t *testing.T) {
+	// make source
+	var src string
+	for _, e := range invalidSegments {
+		src += e.srcline
+	}
+
+	// verify scan
+	var S Scanner
+	var s segment // current segment
+	file := fset.AddFile(filepath.Join("dir", "TestInvalidLineDirectives"), fset.Base(), len(src))
+	S.Init(file, []byte(src), func(pos token.Position, msg string) {
+		if msg != s.filename {
+			t.Errorf("got error %q; want %q", msg, s.filename)
+		}
+		if pos.Line != s.line || pos.Column != s.column {
+			t.Errorf("got position %d:%d; want %d:%d", pos.Line, pos.Column, s.line, s.column)
+		}
+	}, dontInsertSemis)
+	for _, s = range invalidSegments {
+		S.Scan()
+	}
+
+	if S.ErrorCount != len(invalidSegments) {
+		t.Errorf("go %d errors; want %d", S.ErrorCount, len(invalidSegments))
 	}
 }
 
diff --git a/libgo/go/go/token/example_test.go b/libgo/go/go/token/example_test.go
new file mode 100644
index 00000000000..8c0d081ea8a
--- /dev/null
+++ b/libgo/go/go/token/example_test.go
@@ -0,0 +1,79 @@
+// 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 gccgo_examples
+
+package token_test
+
+import (
+	"fmt"
+	"go/ast"
+	"go/parser"
+	"go/token"
+)
+
+func Example_retrievePositionInfo() {
+	fset := token.NewFileSet()
+
+	const src = `package main
+
+import "fmt"
+
+import "go/token"
+
+//line :1:5
+type p = token.Pos
+
+const bad = token.NoPos
+
+//line fake.go:42:11
+func ok(pos p) bool {
+	return pos != bad
+}
+
+/*line :7:9*/func main() {
+	fmt.Println(ok(bad) == bad.IsValid())
+}
+`
+
+	f, err := parser.ParseFile(fset, "main.go", src, 0)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+
+	// Print the location and kind of each declaration in f.
+	for _, decl := range f.Decls {
+		// Get the filename, line, and column back via the file set.
+		// We get both the relative and absolute position.
+		// The relative position is relative to the last line directive.
+		// The absolute position is the exact position in the source.
+		pos := decl.Pos()
+		relPosition := fset.Position(pos)
+		absPosition := fset.PositionFor(pos, false)
+
+		// Either a FuncDecl or GenDecl, since we exit on error.
+		kind := "func"
+		if gen, ok := decl.(*ast.GenDecl); ok {
+			kind = gen.Tok.String()
+		}
+
+		// If the relative and absolute positions differ, show both.
+		fmtPosition := relPosition.String()
+		if relPosition != absPosition {
+			fmtPosition += "[" + absPosition.String() + "]"
+		}
+
+		fmt.Printf("%s: %s\n", fmtPosition, kind)
+	}
+
+	//Output:
+	//
+	// main.go:3:1: import
+	// main.go:5:1: import
+	// main.go:1:5[main.go:8:1]: type
+	// main.go:3:1[main.go:10:1]: const
+	// fake.go:42:11[main.go:13:1]: func
+	// fake.go:7:9[main.go:17:14]: func
+}
diff --git a/libgo/go/go/token/position.go b/libgo/go/go/token/position.go
index 88d74168a1b..241133fe263 100644
--- a/libgo/go/go/token/position.go
+++ b/libgo/go/go/token/position.go
@@ -30,7 +30,9 @@ func (pos *Position) IsValid() bool { return pos.Line > 0 }
 // String returns a string in one of several forms:
 //
 //	file:line:column    valid position with file name
+//	file:line           valid position with file name but no column (column == 0)
 //	line:column         valid position without file name
+//	line                valid position without file name and no column (column == 0)
 //	file                invalid position with file name
 //	-                   invalid position without file name
 //
@@ -40,7 +42,10 @@ func (pos Position) String() string {
 		if s != "" {
 			s += ":"
 		}
-		s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
+		s += fmt.Sprintf("%d", pos.Line)
+		if pos.Column != 0 {
+			s += fmt.Sprintf(":%d", pos.Column)
+		}
 	}
 	if s == "" {
 		s = "-"
@@ -204,28 +209,36 @@ func (f *File) SetLinesForContent(content []byte) {
 	f.mutex.Unlock()
 }
 
-// A lineInfo object describes alternative file and line number
-// information (such as provided via a //line comment in a .go
-// file) for a given file offset.
+// A lineInfo object describes alternative file, line, and column
+// number information (such as provided via a //line directive)
+// for a given file offset.
 type lineInfo struct {
 	// fields are exported to make them accessible to gob
-	Offset   int
-	Filename string
-	Line     int
+	Offset       int
+	Filename     string
+	Line, Column int
 }
 
-// AddLineInfo adds alternative file and line number information for
-// a given file offset. The offset must be larger than the offset for
-// the previously added alternative line info and smaller than the
-// file size; otherwise the information is ignored.
-//
-// AddLineInfo is typically used to register alternative position
-// information for //line filename:line comments in source files.
+// AddLineInfo is like AddLineColumnInfo with a column = 1 argument.
+// It is here for backward-compatibility for code prior to Go 1.11.
 //
 func (f *File) AddLineInfo(offset int, filename string, line int) {
+	f.AddLineColumnInfo(offset, filename, line, 1)
+}
+
+// AddLineColumnInfo adds alternative file, line, and column number
+// information for a given file offset. The offset must be larger
+// than the offset for the previously added alternative line info
+// and smaller than the file size; otherwise the information is
+// ignored.
+//
+// AddLineColumnInfo is typically used to register alternative position
+// information for line directives such as //line filename:line:column.
+//
+func (f *File) AddLineColumnInfo(offset int, filename string, line, column int) {
 	f.mutex.Lock()
 	if i := len(f.infos); i == 0 || f.infos[i-1].Offset < offset && offset < f.size {
-		f.infos = append(f.infos, lineInfo{offset, filename, line})
+		f.infos = append(f.infos, lineInfo{offset, filename, line, column})
 	}
 	f.mutex.Unlock()
 }
@@ -275,12 +288,25 @@ func (f *File) unpack(offset int, adjusted bool) (filename string, line, column
 		line, column = i+1, offset-f.lines[i]+1
 	}
 	if adjusted && len(f.infos) > 0 {
-		// almost no files have extra line infos
+		// few files have extra line infos
 		if i := searchLineInfos(f.infos, offset); i >= 0 {
 			alt := &f.infos[i]
 			filename = alt.Filename
 			if i := searchInts(f.lines, alt.Offset); i >= 0 {
-				line += alt.Line - i - 1
+				// i+1 is the line at which the alternative position was recorded
+				d := line - (i + 1) // line distance from alternative position base
+				line = alt.Line + d
+				if alt.Column == 0 {
+					// alternative column is unknown => relative column is unknown
+					// (the current specification for line directives requires
+					// this to apply until the next PosBase/line directive,
+					// not just until the new newline)
+					column = 0
+				} else if d == 0 {
+					// the alternative position base is on the current line
+					// => column is relative to alternative column
+					column = alt.Column + (offset - alt.Offset)
+				}
 			}
 		}
 	}
diff --git a/libgo/go/go/types/api.go b/libgo/go/go/types/api.go
index 9908f5c9738..fcefddf4883 100644
--- a/libgo/go/go/types/api.go
+++ b/libgo/go/go/types/api.go
@@ -161,14 +161,14 @@ type Info struct {
 	// in package clauses, or symbolic variables t in t := x.(type) of
 	// type switch headers), the corresponding objects are nil.
 	//
-	// For an anonymous field, Defs returns the field *Var it defines.
+	// 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 anonymous field, Uses returns the *TypeName it denotes.
+	// For an embedded field, Uses returns the *TypeName it denotes.
 	//
 	// Invariant: Uses[id].Pos() != id.Pos()
 	Uses map[*ast.Ident]Object
@@ -239,7 +239,7 @@ func (info *Info) TypeOf(e ast.Expr) Type {
 // ObjectOf returns the object denoted by the specified id,
 // or nil if not found.
 //
-// If id is an anonymous struct field, ObjectOf returns the field (*Var)
+// If id is an embedded struct field, ObjectOf returns the field (*Var)
 // it uses, not the type (*TypeName) it defines.
 //
 // Precondition: the Uses and Defs maps are populated.
@@ -309,7 +309,7 @@ func (tv TypeAndValue) Assignable() bool {
 }
 
 // HasOk reports whether the corresponding expression may be
-// used on the lhs of a comma-ok assignment.
+// used on the rhs of a comma-ok assignment.
 func (tv TypeAndValue) HasOk() bool {
 	return tv.mode == commaok || tv.mode == mapindex
 }
diff --git a/libgo/go/go/types/api_test.go b/libgo/go/go/types/api_test.go
index 8a4f1ef9457..d4ed400ea68 100644
--- a/libgo/go/go/types/api_test.go
+++ b/libgo/go/go/types/api_test.go
@@ -26,7 +26,6 @@ func pkgFor(path, source string, info *Info) (*Package, error) {
 	if err != nil {
 		return nil, err
 	}
-
 	conf := Config{Importer: importer.Default()}
 	return conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
 }
@@ -44,6 +43,20 @@ 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 {
+	fset := token.NewFileSet()
+	f, err := parser.ParseFile(fset, path, source, 0)
+	if f == nil { // ignore errors unless f is nil
+		t.Fatalf("%s: unable to parse: %s", path, err)
+	}
+	conf := Config{
+		Error:    func(err error) {},
+		Importer: importer.Default(),
+	}
+	pkg, _ := conf.Check(f.Name.Name, fset, []*ast.File{f}, info)
+	return pkg.Name()
+}
+
 func TestValuesInfo(t *testing.T) {
 	var tests = []struct {
 		src  string
@@ -244,11 +257,16 @@ func TestTypesInfo(t *testing.T) {
 			`<-ch`,
 			`(string, bool)`,
 		},
+
+		// 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`},
 	}
 
 	for _, test := range tests {
 		info := Info{Types: make(map[ast.Expr]TypeAndValue)}
-		name := mustTypecheck(t, "TypesInfo", test.src, &info)
+		name := mayTypecheck(t, "TypesInfo", test.src, &info)
 
 		// look for expression type
 		var typ Type
diff --git a/libgo/go/go/types/assignments.go b/libgo/go/go/types/assignments.go
index 98c9e121b05..27002f66994 100644
--- a/libgo/go/go/types/assignments.go
+++ b/libgo/go/go/types/assignments.go
@@ -153,7 +153,7 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type {
 	var v *Var
 	var v_used bool
 	if ident != nil {
-		if _, obj := check.scope.LookupParent(ident.Name, token.NoPos); obj != nil {
+		if obj := check.lookup(ident.Name); 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.
@@ -279,6 +279,7 @@ func (check *Checker) assignVars(lhs, rhs []ast.Expr) {
 }
 
 func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
+	top := len(check.delayed)
 	scope := check.scope
 
 	// collect lhs variables
@@ -309,6 +310,7 @@ func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
 				check.recordDef(ident, obj)
 			}
 		} else {
+			check.useLHS(lhs)
 			check.errorf(lhs.Pos(), "cannot declare %s", lhs)
 		}
 		if obj == nil {
@@ -319,6 +321,9 @@ func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) {
 
 	check.initVars(lhsVars, rhs, token.NoPos)
 
+	// 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
diff --git a/libgo/go/go/types/builtins.go b/libgo/go/go/types/builtins.go
index 66548231fe4..05e032423ca 100644
--- a/libgo/go/go/types/builtins.go
+++ b/libgo/go/go/types/builtins.go
@@ -158,7 +158,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 			// function calls; in this case s is not evaluated."
 			if !check.hasCallOrRecv {
 				mode = constant_
-				val = constant.MakeInt64(t.len)
+				if t.len >= 0 {
+					val = constant.MakeInt64(t.len)
+				} else {
+					val = constant.MakeUnknown()
+				}
 			}
 
 		case *Slice, *Chan:
@@ -170,7 +174,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 			}
 		}
 
-		if mode == invalid {
+		if mode == invalid && typ != Typ[Invalid] {
 			check.invalidArg(x.pos(), "%s for %s", x, bin.name)
 			return
 		}
@@ -470,6 +474,19 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 
 	case _Panic:
 		// panic(x)
+		// record panic call if inside a function with result parameters
+		// (for use in Checker.isTerminating)
+		if check.sig.results.Len() > 0 {
+			// function has result parameters
+			p := check.isPanic
+			if p == nil {
+				// allocate lazily
+				p = make(map[*ast.CallExpr]bool)
+				check.isPanic = p
+			}
+			p[call] = true
+		}
+
 		check.assignment(x, &emptyInterface, "argument to panic")
 		if x.mode == invalid {
 			return
@@ -606,7 +623,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 		// Note: trace is only available in self-test mode.
 		// (no argument evaluated yet)
 		if nargs == 0 {
-			check.dump("%s: trace() without arguments", call.Pos())
+			check.dump("%v: trace() without arguments", call.Pos())
 			x.mode = novalue
 			break
 		}
@@ -614,7 +631,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 		x1 := x
 		for _, arg := range call.Args {
 			check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T))
-			check.dump("%s: %s", x1.pos(), x1)
+			check.dump("%v: %s", x1.pos(), x1)
 			x1 = &t // use incoming x only for first argument
 		}
 		// trace is only available in test mode - no need to record signature
diff --git a/libgo/go/go/types/call.go b/libgo/go/go/types/call.go
index 8fe65e41d5f..d5c196afe84 100644
--- a/libgo/go/go/types/call.go
+++ b/libgo/go/go/types/call.go
@@ -34,6 +34,7 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
 				check.conversion(x, T)
 			}
 		default:
+			check.use(e.Args...)
 			check.errorf(e.Args[n-1].Pos(), "too many arguments in conversion to %s", T)
 		}
 		x.expr = e
@@ -274,7 +275,7 @@ func (check *Checker) argument(fun ast.Expr, sig *Signature, i int, x *operand,
 		typ = sig.params.vars[n-1].typ
 		if debug {
 			if _, ok := typ.(*Slice); !ok {
-				check.dump("%s: expected unnamed slice type, got %s", sig.params.vars[n-1].Pos(), typ)
+				check.dump("%v: expected unnamed slice type, got %s", sig.params.vars[n-1].Pos(), typ)
 			}
 		}
 	default:
@@ -314,7 +315,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
 	// can only appear in qualified identifiers which are mapped to
 	// selector expressions.
 	if ident, ok := e.X.(*ast.Ident); ok {
-		_, obj := check.scope.LookupParent(ident.Name, check.pos)
+		obj := check.lookup(ident.Name)
 		if pname, _ := obj.(*PkgName); pname != nil {
 			assert(pname.pkg == check.pkg)
 			check.recordUse(ident, pname)
@@ -323,12 +324,12 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
 			exp := pkg.scope.Lookup(sel)
 			if exp == nil {
 				if !pkg.fake {
-					check.errorf(e.Pos(), "%s not declared by package %s", sel, pkg.name)
+					check.errorf(e.Sel.Pos(), "%s not declared by package %s", sel, pkg.name)
 				}
 				goto Error
 			}
 			if !exp.Exported() {
-				check.errorf(e.Pos(), "%s not exported by package %s", sel, pkg.name)
+				check.errorf(e.Sel.Pos(), "%s not exported by package %s", sel, pkg.name)
 				// ok to continue
 			}
 			check.recordUse(e.Sel, exp)
@@ -373,11 +374,11 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
 		switch {
 		case index != nil:
 			// TODO(gri) should provide actual type where the conflict happens
-			check.invalidOp(e.Pos(), "ambiguous selector %s", sel)
+			check.invalidOp(e.Sel.Pos(), "ambiguous selector %s", sel)
 		case indirect:
-			check.invalidOp(e.Pos(), "%s is not in method set of %s", sel, x.typ)
+			check.invalidOp(e.Sel.Pos(), "%s is not in method set of %s", sel, x.typ)
 		default:
-			check.invalidOp(e.Pos(), "%s has no field or method %s", x, sel)
+			check.invalidOp(e.Sel.Pos(), "%s has no field or method %s", x, sel)
 		}
 		goto Error
 	}
@@ -386,7 +387,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
 		// method expression
 		m, _ := obj.(*Func)
 		if m == nil {
-			check.invalidOp(e.Pos(), "%s has no method %s", x, sel)
+			check.invalidOp(e.Sel.Pos(), "%s has no method %s", x, sel)
 			goto Error
 		}
 
@@ -448,7 +449,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
 				// lookup.
 				mset := NewMethodSet(typ)
 				if m := mset.Lookup(check.pkg, sel); m == nil || m.obj != obj {
-					check.dump("%s: (%s).%v -> %s", e.Pos(), typ, obj.name, m)
+					check.dump("%v: (%s).%v -> %s", e.Pos(), typ, obj.name, m)
 					check.dump("%s\n", mset)
 					panic("method sets and lookup don't agree")
 				}
diff --git a/libgo/go/go/types/check.go b/libgo/go/go/types/check.go
index 26db5769b98..76d9c8917cb 100644
--- a/libgo/go/go/types/check.go
+++ b/libgo/go/go/types/check.go
@@ -39,22 +39,22 @@ type exprInfo struct {
 	val   constant.Value // constant value; or nil (if not a constant)
 }
 
-// funcInfo stores the information required for type-checking a function.
-type funcInfo struct {
-	name string    // for debugging/tracing only
-	decl *declInfo // for cycle detection
-	sig  *Signature
-	body *ast.BlockStmt
-}
-
 // A context represents the context within which an object is type-checked.
 type context struct {
-	decl          *declInfo      // package-level declaration whose init expression/function body is checked
-	scope         *Scope         // top-most scope for lookups
-	iota          constant.Value // value of iota in a constant declaration; nil otherwise
-	sig           *Signature     // function signature if inside a function; nil otherwise
-	hasLabel      bool           // set if a function makes use of labels (only ~1% of functions); unused outside functions
-	hasCallOrRecv bool           // set if an expression contains a function call or channel receive operation
+	decl          *declInfo              // package-level declaration whose init expression/function body is checked
+	scope         *Scope                 // top-most scope for lookups
+	pos           token.Pos              // if valid, identifiers are looked up as if at position pos (used by Eval)
+	iota          constant.Value         // value of iota in a constant declaration; nil otherwise
+	sig           *Signature             // function signature if inside a function; nil otherwise
+	isPanic       map[*ast.CallExpr]bool // set of panic call expressions (used for termination check)
+	hasLabel      bool                   // set if a function makes use of labels (only ~1% of functions); unused outside functions
+	hasCallOrRecv bool                   // set if an expression contains a function call or channel receive operation
+}
+
+// lookup looks up name in the current context and returns the matching object, or nil.
+func (ctxt *context) lookup(name string) Object {
+	_, obj := ctxt.scope.LookupParent(name, ctxt.pos)
+	return obj
 }
 
 // An importKey identifies an imported package by import path and source directory
@@ -85,16 +85,16 @@ type Checker struct {
 	files            []*ast.File                       // package files
 	unusedDotImports map[*Scope]map[*Package]token.Pos // positions of unused dot-imported packages for each file scope
 
-	firstErr error                 // first error encountered
-	methods  map[string][]*Func    // maps type names to associated methods
-	untyped  map[ast.Expr]exprInfo // map of expressions without final type
-	funcs    []funcInfo            // list of functions to type-check
-	delayed  []func()              // delayed checks requiring fully setup types
+	firstErr   error                    // first error encountered
+	methods    map[*TypeName][]*Func    // maps package scope type names to associated non-blank, non-interface methods
+	interfaces map[*TypeName]*ifaceInfo // maps interface type names to corresponding interface infos
+	untyped    map[ast.Expr]exprInfo    // map of expressions without final type
+	delayed    []func()                 // stack of delayed actions
+	objPath    []Object                 // path of object dependencies during type inference (for cycle reporting)
 
 	// context within which the current object is type-checked
 	// (valid only for the duration of type-checking a specific object)
 	context
-	pos token.Pos // if valid, identifiers are looked up as if at position pos (used by Eval)
 
 	// debugging
 	indent int // indentation for tracing
@@ -128,15 +128,6 @@ func (check *Checker) addDeclDep(to Object) {
 	from.addDep(to)
 }
 
-func (check *Checker) assocMethod(tname string, meth *Func) {
-	m := check.methods
-	if m == nil {
-		m = make(map[string][]*Func)
-		check.methods = m
-	}
-	m[tname] = append(m[tname], meth)
-}
-
 func (check *Checker) rememberUntyped(e ast.Expr, lhs bool, mode operandMode, typ *Basic, val constant.Value) {
 	m := check.untyped
 	if m == nil {
@@ -146,12 +137,32 @@ func (check *Checker) rememberUntyped(e ast.Expr, lhs bool, mode operandMode, ty
 	m[e] = exprInfo{lhs, mode, typ, val}
 }
 
-func (check *Checker) later(name string, decl *declInfo, sig *Signature, body *ast.BlockStmt) {
-	check.funcs = append(check.funcs, funcInfo{name, decl, sig, body})
+// later pushes f on to the stack of actions that will be processed later;
+// either at the end of the current statement, or in case of a local constant
+// or variable declaration, before the constant or variable is in scope
+// (so that f still sees the scope before any new declarations).
+func (check *Checker) later(f func()) {
+	check.delayed = append(check.delayed, f)
 }
 
-func (check *Checker) delay(f func()) {
-	check.delayed = append(check.delayed, 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)
+	return len(check.objPath) - 1
+}
+
+// pop pops and returns the topmost object from the object path.
+func (check *Checker) pop() Object {
+	i := len(check.objPath) - 1
+	obj := check.objPath[i]
+	check.objPath[i] = nil
+	check.objPath = check.objPath[:i]
+	return obj
+}
+
+// pathString returns a string of the form a->b-> ... ->g for an object path [a, b, ... g].
+func (check *Checker) pathString() string {
+	return objPathString(check.objPath)
 }
 
 // NewChecker returns a new Checker instance for a given package.
@@ -186,8 +197,8 @@ func (check *Checker) initFiles(files []*ast.File) {
 
 	check.firstErr = nil
 	check.methods = nil
+	check.interfaces = nil
 	check.untyped = nil
-	check.funcs = nil
 	check.delayed = nil
 
 	// determine package name and collect valid files
@@ -236,9 +247,9 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
 
 	check.collectObjects()
 
-	check.packageObjects(check.resolveOrder())
+	check.packageObjects()
 
-	check.functionBodies()
+	check.processDelayed(0) // incl. all functions
 
 	check.initOrder()
 
@@ -246,11 +257,6 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
 		check.unusedImports()
 	}
 
-	// perform delayed checks
-	for _, f := range check.delayed {
-		f()
-	}
-
 	check.recordUntyped()
 
 	check.pkg.complete = true
@@ -264,7 +270,7 @@ func (check *Checker) recordUntyped() {
 
 	for x, info := range check.untyped {
 		if debug && isTyped(info.typ) {
-			check.dump("%s: %s (type %s) is typed", x.Pos(), x, info.typ)
+			check.dump("%v: %s (type %s) is typed", x.Pos(), x, info.typ)
 			unreachable()
 		}
 		check.recordTypeAndValue(x, info.mode, info.typ, info.val)
diff --git a/libgo/go/go/types/check_test.go b/libgo/go/go/types/check_test.go
index e3ca90a6bdc..2bdfc150f41 100644
--- a/libgo/go/go/types/check_test.go
+++ b/libgo/go/go/types/check_test.go
@@ -61,6 +61,7 @@ var tests = [][]string{
 	{"testdata/cycles2.src"},
 	{"testdata/cycles3.src"},
 	{"testdata/cycles4.src"},
+	{"testdata/cycles5.src"},
 	{"testdata/init0.src"},
 	{"testdata/init1.src"},
 	{"testdata/init2.src"},
@@ -89,6 +90,8 @@ var tests = [][]string{
 	{"testdata/labels.src"},
 	{"testdata/issues.src"},
 	{"testdata/blank.src"},
+	{"testdata/issue25008b.src", "testdata/issue25008a.src"}, // order (b before a) is crucial!
+	{"testdata/issue26390.src"},                              // stand-alone test to ensure case is triggered
 }
 
 var fset = token.NewFileSet()
diff --git a/libgo/go/go/types/decl.go b/libgo/go/go/types/decl.go
index 9b250b30e74..11b68583e38 100644
--- a/libgo/go/go/types/decl.go
+++ b/libgo/go/go/types/decl.go
@@ -37,15 +37,45 @@ func (check *Checker) declare(scope *Scope, id *ast.Ident, obj Object, pos token
 	}
 }
 
+// pathString returns a string of the form a->b-> ... ->g for a path [a, b, ... g].
+// TODO(gri) remove once we don't need the old cycle detection (explicitly passed
+//           []*TypeName path) anymore
+func pathString(path []*TypeName) string {
+	var s string
+	for i, p := range path {
+		if i > 0 {
+			s += "->"
+		}
+		s += p.Name()
+	}
+	return s
+}
+
+// objPathString returns a string of the form a->b-> ... ->g for a path [a, b, ... g].
+// TODO(gri) s/objPathString/pathString/ once we got rid of pathString above
+func objPathString(path []Object) string {
+	var s string
+	for i, p := range path {
+		if i > 0 {
+			s += "->"
+		}
+		s += p.Name()
+	}
+	return s
+}
+
+// useCycleMarking enables the new coloring-based cycle marking scheme
+// for package-level objects. Set this flag to false to disable this
+// code quickly and revert to the existing mechanism (and comment out
+// some of the new tests in cycles5.src that will fail again).
+// TODO(gri) remove this for Go 1.12
+const useCycleMarking = true
+
 // objDecl type-checks the declaration of obj in its respective (file) context.
 // See check.typ for the details on def and path.
 func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
-	if obj.Type() != nil {
-		return // already checked - nothing to do
-	}
-
 	if trace {
-		check.trace(obj.Pos(), "-- declaring %s", obj.Name())
+		check.trace(obj.Pos(), "-- checking %s %s (path = %s, objPath = %s)", obj.color(), obj, pathString(path), check.pathString())
 		check.indent++
 		defer func() {
 			check.indent--
@@ -53,9 +83,142 @@ func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
 		}()
 	}
 
+	// Checking the declaration of obj means inferring its type
+	// (and possibly its value, for constants).
+	// An object's type (and thus the object) may be in one of
+	// three states which are expressed by colors:
+	//
+	// - an object whose type is not yet known is painted white (initial color)
+	// - an object whose type is in the process of being inferred is painted grey
+	// - an object whose type is fully inferred is painted black
+	//
+	// During type inference, an object's color changes from white to grey
+	// to black (pre-declared objects are painted black from the start).
+	// A black object (i.e., its type) can only depend on (refer to) other black
+	// ones. White and grey objects may depend on white and black objects.
+	// A dependency on a grey object indicates a cycle which may or may not be
+	// valid.
+	//
+	// When objects turn grey, they are pushed on the object path (a stack);
+	// they are popped again when they turn black. Thus, if a grey object (a
+	// cycle) is encountered, it is on the object path, and all the objects
+	// it depends on are the remaining objects on that path. Color encoding
+	// is such that the color value of a grey object indicates the index of
+	// that object in the object path.
+
+	// During type-checking, white objects may be assigned a type without
+	// traversing through objDecl; e.g., when initializing constants and
+	// variables. Update the colors of those objects here (rather than
+	// everywhere where we set the type) to satisfy the color invariants.
+	if obj.color() == white && obj.Type() != nil {
+		obj.setColor(black)
+		return
+	}
+
+	switch obj.color() {
+	case white:
+		assert(obj.Type() == nil)
+		// All color values other than white and black are considered grey.
+		// Because black and white are < grey, all values >= grey are grey.
+		// Use those values to encode the object's index into the object path.
+		obj.setColor(grey + color(check.push(obj)))
+		defer func() {
+			check.pop().setColor(black)
+		}()
+
+	case black:
+		assert(obj.Type() != nil)
+		return
+
+	default:
+		// Color values other than white or black are considered grey.
+		fallthrough
+
+	case grey:
+		// We have a cycle.
+		// In the existing code, this is marked by a non-nil type
+		// for the object except for constants and variables whose
+		// type may be non-nil (known), or nil if it depends on the
+		// not-yet known initialization value.
+		// In the former case, set the type to Typ[Invalid] because
+		// we have an initialization cycle. The cycle error will be
+		// reported later, when determining initialization order.
+		// TODO(gri) Report cycle here and simplify initialization
+		// order code.
+		switch obj := obj.(type) {
+		case *Const:
+			if useCycleMarking && check.typeCycle(obj) {
+				obj.typ = Typ[Invalid]
+				break
+			}
+			if obj.typ == nil {
+				obj.typ = Typ[Invalid]
+			}
+
+		case *Var:
+			if useCycleMarking && check.typeCycle(obj) {
+				obj.typ = Typ[Invalid]
+				break
+			}
+			if obj.typ == nil {
+				obj.typ = Typ[Invalid]
+			}
+
+		case *TypeName:
+			// fixFor26390 enables a temporary work-around to handle alias type names
+			// that have not been given a type yet even though the underlying type
+			// is already known. See testdata/issue26390.src for a simple example.
+			// Set this flag to false to disable this code quickly (and comment
+			// out the new test in decls4.src that will fail again).
+			// TODO(gri) remove this for Go 1.12 in favor of a more comprehensive fix
+			const fixFor26390 = true
+			if fixFor26390 {
+				// If we have a package-level alias type name that has not been
+				// given a type yet but the underlying type is a type name that
+				// has been given a type already, don't report a cycle but use
+				// the underlying type name's type instead. The cycle shouldn't
+				// exist in the first place in this case and is due to the way
+				// methods are type-checked at the moment. See also the comment
+				// at the end of Checker.typeDecl below.
+				if d := check.objMap[obj]; d != nil && d.alias && obj.typ == Typ[Invalid] {
+					// If we can find the underlying type name syntactically
+					// and it has a type, use that type.
+					if tname := check.resolveBaseTypeName(ast.NewIdent(obj.name)); tname != nil && tname.typ != nil {
+						obj.typ = tname.typ
+						break
+					}
+				}
+			}
+
+			if useCycleMarking && check.typeCycle(obj) {
+				// break cycle
+				// (without this, calling underlying()
+				// below may lead to an endless loop
+				// if we have a cycle for a defined
+				// (*Named) type)
+				obj.typ = Typ[Invalid]
+			}
+
+		case *Func:
+			if useCycleMarking && check.typeCycle(obj) {
+				// Don't set obj.typ to Typ[Invalid] here
+				// because plenty of code type-asserts that
+				// functions have a *Signature type. Grey
+				// functions have their type set to an empty
+				// signature which makes it impossible to
+				// initialize a variable with the function.
+			}
+
+		default:
+			unreachable()
+		}
+		assert(obj.Type() != nil)
+		return
+	}
+
 	d := check.objMap[obj]
 	if d == nil {
-		check.dump("%s: %s should have been declared", obj.Pos(), obj.Name())
+		check.dump("%v: %s should have been declared", obj.Pos(), obj)
 		unreachable()
 	}
 
@@ -90,17 +253,118 @@ func (check *Checker) objDecl(obj Object, def *Named, path []*TypeName) {
 	}
 }
 
+// indir is a sentinel type name that is pushed onto the object path
+// to indicate an "indirection" in the dependency from one type name
+// to the next. For instance, for "type p *p" the object path contains
+// p followed by indir, indicating that there's an indirection *p.
+// Indirections are used to break type cycles.
+var indir = NewTypeName(token.NoPos, nil, "*", nil)
+
+// cutCycle is a sentinel type name that is pushed onto the object path
+// to indicate that a cycle doesn't actually exist. This is currently
+// needed to break cycles formed via method declarations because they
+// are type-checked together with their receiver base types. Once methods
+// are type-checked separately (see also TODO in Checker.typeDecl), we
+// can get rid of this.
+var cutCycle = NewTypeName(token.NoPos, nil, "!", nil)
+
+// typeCycle checks if the cycle starting with obj is valid and
+// reports an error if it is not.
+// TODO(gri) rename s/typeCycle/cycle/ once we don't need the other
+// cycle method anymore.
+func (check *Checker) typeCycle(obj Object) (isCycle bool) {
+	d := check.objMap[obj]
+	if d == nil {
+		check.dump("%v: %s should have been declared", obj.Pos(), obj)
+		unreachable()
+	}
+
+	// Given the number of constants and variables (nval) in the cycle
+	// and the cycle length (ncycle = number of named objects in the cycle),
+	// we distinguish between cycles involving only constants and variables
+	// (nval = ncycle), cycles involving types (and functions) only
+	// (nval == 0), and mixed cycles (nval != 0 && nval != ncycle).
+	// We ignore functions at the moment (taking them into account correctly
+	// is complicated and it doesn't improve error reporting significantly).
+	//
+	// A cycle must have at least one indirection and one type definition
+	// to be permitted: If there is no indirection, the size of the type
+	// cannot be computed (it's either infinite or 0); if there is no type
+	// definition, we have a sequence of alias type names which will expand
+	// ad infinitum.
+	var nval, ncycle int
+	var hasIndir, hasTDef bool
+	assert(obj.color() >= grey)
+	start := obj.color() - grey // index of obj in objPath
+	cycle := check.objPath[start:]
+	ncycle = len(cycle) // including indirections
+	for _, obj := range cycle {
+		switch obj := obj.(type) {
+		case *Const, *Var:
+			nval++
+		case *TypeName:
+			switch {
+			case obj == indir:
+				ncycle-- // don't count (indirections are not objects)
+				hasIndir = true
+			case obj == cutCycle:
+				// The cycle is not real and only caused by the fact
+				// that we type-check methods when we type-check their
+				// receiver base types.
+				return false
+			case !check.objMap[obj].alias:
+				hasTDef = true
+			}
+		case *Func:
+			// ignored for now
+		default:
+			unreachable()
+		}
+	}
+
+	if trace {
+		check.trace(obj.Pos(), "## cycle detected: objPath = %s->%s (len = %d)", objPathString(cycle), obj.Name(), ncycle)
+		check.trace(obj.Pos(), "## cycle contains: %d values, has indirection = %v, has type definition = %v", nval, hasIndir, hasTDef)
+		defer func() {
+			if isCycle {
+				check.trace(obj.Pos(), "=> error: cycle is invalid")
+			}
+		}()
+	}
+
+	// A cycle involving only constants and variables is invalid but we
+	// ignore them here because they are reported via the initialization
+	// cycle check.
+	if nval == ncycle {
+		return false
+	}
+
+	// A cycle involving only types (and possibly functions) must have at
+	// least one indirection and one type definition to be permitted: If
+	// there is no indirection, the size of the type cannot be computed
+	// (it's either infinite or 0); if there is no type definition, we
+	// have a sequence of alias type names which will expand ad infinitum.
+	if nval == 0 && hasIndir && hasTDef {
+		return false // cycle is permitted
+	}
+
+	// report cycle
+	check.errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name())
+	for _, obj := range cycle {
+		if obj == indir {
+			continue // don't print indir sentinels
+		}
+		check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
+	}
+	check.errorf(obj.Pos(), "\t%s", obj.Name())
+
+	return true
+}
+
 func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
 	assert(obj.typ == nil)
 
-	if obj.visited {
-		obj.typ = Typ[Invalid]
-		return
-	}
-	obj.visited = true
-
 	// use the correct value of iota
-	assert(check.iota == nil)
 	check.iota = obj.val
 	defer func() { check.iota = nil }()
 
@@ -109,7 +373,7 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
 
 	// determine type, if any
 	if typ != nil {
-		t := check.typ(typ)
+		t := check.typExpr(typ, nil, nil)
 		if !isConstType(t) {
 			// don't report an error if the type is an invalid C (defined) type
 			// (issue #22090)
@@ -133,18 +397,9 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) {
 func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init ast.Expr) {
 	assert(obj.typ == nil)
 
-	if obj.visited {
-		obj.typ = Typ[Invalid]
-		return
-	}
-	obj.visited = true
-
-	// var declarations cannot use iota
-	assert(check.iota == nil)
-
 	// determine type, if any
 	if typ != nil {
-		obj.typ = check.typ(typ)
+		obj.typ = check.typExpr(typ, nil, nil)
 		// 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,
@@ -222,9 +477,6 @@ func (n *Named) setUnderlying(typ Type) {
 func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, path []*TypeName, alias bool) {
 	assert(obj.typ == nil)
 
-	// type declarations cannot use iota
-	assert(check.iota == nil)
-
 	if alias {
 
 		obj.typ = Typ[Invalid]
@@ -266,18 +518,22 @@ func (check *Checker) typeDecl(obj *TypeName, typ ast.Expr, def *Named, path []*
 
 func (check *Checker) addMethodDecls(obj *TypeName) {
 	// get associated methods
-	methods := check.methods[obj.name]
-	if len(methods) == 0 {
-		return // no methods
+	// (Checker.collectObjects only collects methods with non-blank names;
+	// Checker.resolveBaseTypeName ensures that obj is not an alias name
+	// if it has attached methods.)
+	methods := check.methods[obj]
+	if methods == nil {
+		return
 	}
-	delete(check.methods, obj.name)
+	delete(check.methods, obj)
+	assert(!check.objMap[obj].alias) // 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) // nil if receiver base type is type alias
+	base, _ := obj.typ.(*Named) // shouldn't fail but be conservative
 	if base != nil {
 		if t, _ := base.underlying.(*Struct); t != nil {
 			for _, fld := range t.fields {
@@ -296,30 +552,38 @@ func (check *Checker) addMethodDecls(obj *TypeName) {
 		}
 	}
 
+	if useCycleMarking {
+		// Suppress detection of type cycles occurring through method
+		// declarations - they wouldn't exist if methods were type-
+		// checked separately from their receiver base types. See also
+		// comment at the end of Checker.typeDecl.
+		// TODO(gri) Remove this once methods are type-checked separately.
+		check.push(cutCycle)
+		defer check.pop()
+	}
+
 	// type-check methods
 	for _, m := range methods {
 		// spec: "For a base type, the non-blank names of methods bound
 		// to it must be unique."
-		if m.name != "_" {
-			if alt := mset.insert(m); alt != nil {
-				switch alt.(type) {
-				case *Var:
-					check.errorf(m.pos, "field and method with the same name %s", m.name)
-				case *Func:
-					check.errorf(m.pos, "method %s already declared for %s", m.name, obj)
-				default:
-					unreachable()
-				}
-				check.reportAltDecl(alt)
-				continue
+		assert(m.name != "_")
+		if alt := mset.insert(m); alt != nil {
+			switch alt.(type) {
+			case *Var:
+				check.errorf(m.pos, "field and method with the same name %s", m.name)
+			case *Func:
+				check.errorf(m.pos, "method %s already declared for %s", m.name, obj)
+			default:
+				unreachable()
 			}
+			check.reportAltDecl(alt)
+			continue
 		}
 
 		// type-check
 		check.objDecl(m, nil, nil)
 
-		// methods with blank _ names cannot be found - don't keep them
-		if base != nil && m.name != "_" {
+		if base != nil {
 			base.methods = append(base.methods, m)
 		}
 	}
@@ -343,7 +607,9 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
 	// function body must be type-checked after global declarations
 	// (functions implemented elsewhere have no body)
 	if !check.conf.IgnoreFuncBodies && fdecl.Body != nil {
-		check.later(obj.name, decl, sig, fdecl.Body)
+		check.later(func() {
+			check.funcBody(decl, obj.name, sig, fdecl.Body, nil)
+		})
 	}
 }
 
@@ -361,6 +627,8 @@ func (check *Checker) declStmt(decl ast.Decl) {
 			case *ast.ValueSpec:
 				switch d.Tok {
 				case token.CONST:
+					top := len(check.delayed)
+
 					// determine which init exprs to use
 					switch {
 					case s.Type != nil || len(s.Values) > 0:
@@ -385,6 +653,9 @@ func (check *Checker) declStmt(decl ast.Decl) {
 
 					check.arityMatch(s, last)
 
+					// process function literals in init expressions before scope changes
+					check.processDelayed(top)
+
 					// 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
@@ -395,6 +666,8 @@ func (check *Checker) declStmt(decl ast.Decl) {
 					}
 
 				case token.VAR:
+					top := len(check.delayed)
+
 					lhs0 := make([]*Var, len(s.Names))
 					for i, name := range s.Names {
 						lhs0[i] = NewVar(name.Pos(), pkg, name.Name, nil)
@@ -435,6 +708,9 @@ func (check *Checker) declStmt(decl ast.Decl) {
 
 					check.arityMatch(s, nil)
 
+					// process function literals in init expressions before scope changes
+					check.processDelayed(top)
+
 					// declare all variables
 					// (only at this point are the variable scopes (parents) set)
 					scopePos := s.End() // see constant declarations
diff --git a/libgo/go/go/types/errors.go b/libgo/go/go/types/errors.go
index 0c0049b1f3e..4c8d8537ee6 100644
--- a/libgo/go/go/types/errors.go
+++ b/libgo/go/go/types/errors.go
@@ -67,10 +67,20 @@ func (check *Checker) dump(format string, args ...interface{}) {
 }
 
 func (check *Checker) err(pos token.Pos, msg string, soft bool) {
+	// Cheap trick: Don't report errors with messages containing
+	// "invalid operand" or "invalid type" as those tend to be
+	// follow-on errors which don't add useful information. Only
+	// exclude them if these strings are not at the beginning,
+	// and only if we have at least one error already reported.
+	if check.firstErr != nil && (strings.Index(msg, "invalid operand") > 0 || strings.Index(msg, "invalid type") > 0) {
+		return
+	}
+
 	err := Error{check.fset, pos, msg, soft}
 	if check.firstErr == nil {
 		check.firstErr = err
 	}
+
 	f := check.conf.Error
 	if f == nil {
 		panic(bailout{}) // report only first error
diff --git a/libgo/go/go/types/eval.go b/libgo/go/go/types/eval.go
index 831d771d807..8d4db48a9f9 100644
--- a/libgo/go/go/types/eval.go
+++ b/libgo/go/go/types/eval.go
@@ -16,9 +16,6 @@ import (
 // complete position information relative to the provided file
 // set.
 //
-// If the expression contains function literals, their bodies
-// are ignored (i.e., the bodies are not type-checked).
-//
 // If pkg == nil, the Universe scope is used and the provided
 // position pos is ignored. If pkg != nil, and pos is invalid,
 // the package scope is used. Otherwise, pos must belong to the
@@ -34,7 +31,7 @@ import (
 // level untyped constants will return an untyped type rather then the
 // respective context-specific type.
 //
-func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (TypeAndValue, error) {
+func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (_ TypeAndValue, err error) {
 	// determine scope
 	var scope *Scope
 	if pkg == nil {
@@ -79,5 +76,7 @@ func Eval(fset *token.FileSet, pkg *Package, pos token.Pos, expr string) (TypeAn
 	// evaluate node
 	var x operand
 	check.rawExpr(&x, node, nil)
-	return TypeAndValue{x.mode, x.typ, x.val}, err
+	check.processDelayed(0) // incl. all functions
+
+	return TypeAndValue{x.mode, x.typ, x.val}, nil
 }
diff --git a/libgo/go/go/types/eval_test.go b/libgo/go/go/types/eval_test.go
index 603211257dc..d3b3fec66fc 100644
--- a/libgo/go/go/types/eval_test.go
+++ b/libgo/go/go/types/eval_test.go
@@ -149,6 +149,19 @@ func TestEvalPos(t *testing.T) {
 		package p
 		/* T => , p.T */
 		`,
+		`
+		package p
+		import "io"
+		type R = io.Reader
+		func _() {
+			/* 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) */
+				type io interface {} // must not shadow io in line above
+			}
+			type R interface {} // must not shadow R in first line of this function body
+		}
+		`,
 	}
 
 	fset := token.NewFileSet()
diff --git a/libgo/go/go/types/expr.go b/libgo/go/go/types/expr.go
index 59534c75708..c1deaf8325a 100644
--- a/libgo/go/go/types/expr.go
+++ b/libgo/go/go/types/expr.go
@@ -382,7 +382,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) {
 		// The respective sub-expressions got their final types
 		// upon assignment or use.
 		if debug {
-			check.dump("%s: found old type(%s): %s (new: %s)", x.Pos(), x, old.typ, typ)
+			check.dump("%v: found old type(%s): %s (new: %s)", x.Pos(), x, old.typ, typ)
 			unreachable()
 		}
 		return
@@ -1030,16 +1030,15 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 			// Anonymous functions are considered part of the
 			// init expression/func declaration which contains
 			// them: use existing package-level declaration info.
-			//
-			// TODO(gri) We delay type-checking of regular (top-level)
-			//           function bodies until later. Why don't we do
-			//           it for closures of top-level expressions?
-			//           (We can't easily do it for local closures
-			//           because the surrounding scopes must reflect
-			//           the exact position where the closure appears
-			//           in the source; e.g., variables declared below
-			//           must not be visible).
-			check.funcBody(check.decl, "", sig, e.Body)
+			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, "", sig, e.Body, iota)
+			})
 			x.mode = value
 			x.typ = sig
 		} else {
@@ -1065,7 +1064,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 					break
 				}
 			}
-			typ = check.typ(e.Type)
+			typ = check.typExpr(e.Type, nil, nil)
 			base = typ
 
 		case hint != nil:
@@ -1095,6 +1094,9 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 						continue
 					}
 					key, _ := kv.Key.(*ast.Ident)
+					// do all possible checks early (before exiting due to errors)
+					// so we don't drop information on the floor
+					check.expr(x, kv.Value)
 					if key == nil {
 						check.errorf(kv.Pos(), "invalid field name %s in struct literal", kv.Key)
 						continue
@@ -1106,15 +1108,14 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 					}
 					fld := fields[i]
 					check.recordUse(key, fld)
+					etyp := fld.typ
+					check.assignment(x, etyp, "struct literal")
 					// 0 <= i < len(fields)
 					if visited[i] {
 						check.errorf(kv.Pos(), "duplicate field name %s in struct literal", key.Name)
 						continue
 					}
 					visited[i] = true
-					check.expr(x, kv.Value)
-					etyp := fld.typ
-					check.assignment(x, etyp, "struct literal")
 				}
 			} else {
 				// no element must have a key
@@ -1432,7 +1433,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 			check.invalidAST(e.Pos(), "use of .(type) outside type switch")
 			goto Error
 		}
-		T := check.typ(e.Type)
+		T := check.typExpr(e.Type, nil, nil)
 		if T == Typ[Invalid] {
 			goto Error
 		}
diff --git a/libgo/go/go/types/gotype.go b/libgo/go/go/types/gotype.go
index 196fc9bbd60..cde373f3556 100644
--- a/libgo/go/go/types/gotype.go
+++ b/libgo/go/go/types/gotype.go
@@ -53,6 +53,8 @@ Flags controlling additional output:
 		print parse trace (forces -seq)
 	-comments
 		parse comments (ignored unless -ast or -trace is provided)
+	-panic
+		panic on first error
 
 Examples:
 
@@ -105,6 +107,7 @@ var (
 	printAST      = flag.Bool("ast", false, "print AST (forces -seq)")
 	printTrace    = flag.Bool("trace", false, "print parse trace (forces -seq)")
 	parseComments = flag.Bool("comments", false, "parse comments (ignored unless -ast or -trace is provided)")
+	panicOnError  = flag.Bool("panic", false, "panic on first error")
 )
 
 var (
@@ -164,6 +167,9 @@ func usage() {
 }
 
 func report(err error) {
+	if *panicOnError {
+		panic(err)
+	}
 	scanner.PrintError(os.Stderr, err)
 	if list, ok := err.(scanner.ErrorList); ok {
 		errorCount += len(list)
@@ -209,14 +215,30 @@ func parseFiles(dir string, filenames []string) ([]*ast.File, error) {
 	}
 	wg.Wait()
 
-	// if there are errors, return the first one for deterministic results
+	// If there are errors, return the first one for deterministic results.
+	var first error
 	for _, err := range errors {
 		if err != nil {
-			return nil, err
+			first = err
+			// If we have an error, some files may be nil.
+			// Remove them. (The go/parser always returns
+			// a possibly partial AST even in the presence
+			// of errors, except if the file doesn't exist
+			// in the first place, in which case it cannot
+			// matter.)
+			i := 0
+			for _, f := range files {
+				if f != nil {
+					files[i] = f
+					i++
+				}
+			}
+			files = files[:i]
+			break
 		}
 	}
 
-	return files, nil
+	return files, first
 }
 
 func parseDir(dir string) ([]*ast.File, error) {
@@ -318,7 +340,7 @@ func main() {
 	files, err := getPkgFiles(flag.Args())
 	if err != nil {
 		report(err)
-		os.Exit(2)
+		// ok to continue (files may be empty, but not nil)
 	}
 
 	checkPkgFiles(files)
diff --git a/libgo/go/go/types/interfaces.go b/libgo/go/go/types/interfaces.go
new file mode 100644
index 00000000000..e4b42dc5a36
--- /dev/null
+++ b/libgo/go/go/types/interfaces.go
@@ -0,0 +1,443 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this src code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import (
+	"bytes"
+	"fmt"
+	"go/ast"
+	"go/token"
+)
+
+// This file implements the collection of an interface's methods
+// without relying on partially computed types of methods or interfaces
+// for interface types declared at the package level.
+//
+// Because interfaces must not embed themselves, directly or indirectly,
+// the method set of a valid interface can always be computed independent
+// of any cycles that might exist via method signatures (see also issue #18395).
+//
+// Except for blank method name and interface cycle errors, no errors
+// are reported. Affected methods or embedded interfaces are silently
+// dropped. Subsequent type-checking of the interface will check
+// signatures and embedded interfaces and report errors at that time.
+//
+// Only infoFromTypeLit should be called directly from code outside this file
+// to compute an ifaceInfo.
+
+// ifaceInfo describes the method set for an interface.
+// The zero value for an ifaceInfo is a ready-to-use ifaceInfo representing
+// the empty interface.
+type ifaceInfo struct {
+	explicits int           // number of explicitly declared methods
+	methods   []*methodInfo // all methods, starting with explicitly declared ones in source order
+}
+
+// emptyIfaceInfo represents the ifaceInfo for the empty interface.
+var emptyIfaceInfo ifaceInfo
+
+func (info *ifaceInfo) String() string {
+	var buf bytes.Buffer
+	fmt.Fprintf(&buf, "interface{")
+	for i, m := range info.methods {
+		if i > 0 {
+			fmt.Fprint(&buf, " ")
+		}
+		fmt.Fprint(&buf, m)
+	}
+	fmt.Fprintf(&buf, "}")
+	return buf.String()
+}
+
+// methodInfo represents an interface method.
+// At least one of src or fun must be non-nil.
+// (Methods declared in the current package have a non-nil scope
+// and src, and eventually a non-nil fun field; imported and pre-
+// declared methods have a nil scope and src, and only a non-nil
+// fun field.)
+type methodInfo struct {
+	scope *Scope     // scope of interface method; or nil
+	src   *ast.Field // syntax tree representation of interface method; or nil
+	fun   *Func      // corresponding fully type-checked method type; or nil
+}
+
+func (info *methodInfo) String() string {
+	if info.fun != nil {
+		return info.fun.name
+	}
+	return info.src.Names[0].Name
+}
+
+func (info *methodInfo) Pos() token.Pos {
+	if info.fun != nil {
+		return info.fun.Pos()
+	}
+	return info.src.Pos()
+}
+
+func (info *methodInfo) id(pkg *Package) string {
+	if info.fun != nil {
+		return info.fun.Id()
+	}
+	return Id(pkg, info.src.Names[0].Name)
+}
+
+// A methodInfoSet maps method ids to methodInfos.
+// It is used to determine duplicate declarations.
+// (A methodInfo set is the equivalent of an objset
+// but for methodInfos rather than Objects.)
+type methodInfoSet map[string]*methodInfo
+
+// insert attempts to insert an method m into the method set s.
+// If s already contains an alternative method alt with
+// the same name, insert leaves s unchanged and returns alt.
+// Otherwise it inserts m and returns nil.
+func (s *methodInfoSet) insert(pkg *Package, m *methodInfo) *methodInfo {
+	id := m.id(pkg)
+	if alt := (*s)[id]; alt != nil {
+		return alt
+	}
+	if *s == nil {
+		*s = make(methodInfoSet)
+	}
+	(*s)[id] = m
+	return nil
+}
+
+// like Checker.declareInSet but for method infos.
+func (check *Checker) declareInMethodSet(mset *methodInfoSet, pos token.Pos, m *methodInfo) bool {
+	if alt := mset.insert(check.pkg, m); alt != nil {
+		check.errorf(pos, "%s redeclared", m)
+		check.reportAltMethod(alt)
+		return false
+	}
+	return true
+}
+
+// like Checker.reportAltDecl but for method infos.
+func (check *Checker) reportAltMethod(m *methodInfo) {
+	if pos := m.Pos(); pos.IsValid() {
+		// We use "other" rather than "previous" here because
+		// the first declaration seen may not be textually
+		// earlier in the source.
+		check.errorf(pos, "\tother declaration of %s", m) // secondary error, \t indented
+	}
+}
+
+// infoFromTypeLit computes the method set for the given interface iface
+// declared in scope.
+// If a corresponding type name exists (tname != nil), it is used for
+// cycle detection and to cache the method set.
+// The result is the method set, or nil if there is a cycle via embedded
+// interfaces. A non-nil result doesn't mean that there were no errors,
+// but they were either reported (e.g., blank methods), or will be found
+// (again) when computing the interface's type.
+// If tname is not nil it must be the last element in path.
+func (check *Checker) infoFromTypeLit(scope *Scope, iface *ast.InterfaceType, tname *TypeName, path []*TypeName) (info *ifaceInfo) {
+	assert(iface != nil)
+
+	// lazy-allocate interfaces map
+	if check.interfaces == nil {
+		check.interfaces = make(map[*TypeName]*ifaceInfo)
+	}
+
+	if trace {
+		check.trace(iface.Pos(), "-- collect methods for %v (path = %s, objPath = %s)", iface, pathString(path), check.pathString())
+		check.indent++
+		defer func() {
+			check.indent--
+			check.trace(iface.Pos(), "=> %s", info)
+		}()
+	}
+
+	// If the interface is named, check if we computed info already.
+	//
+	// This is not simply an optimization; we may run into stack
+	// overflow with recursive interface declarations. Example:
+	//
+	//      type T interface {
+	//              m() interface { T }
+	//      }
+	//
+	// (Since recursive definitions can only be expressed via names,
+	// it is sufficient to track named interfaces here.)
+	//
+	// While at it, use the same mechanism to detect cycles. (We still
+	// have the path-based cycle check because we want to report the
+	// entire cycle if present.)
+	if tname != nil {
+		assert(path[len(path)-1] == tname) // tname must be last path element
+		var found bool
+		if info, found = check.interfaces[tname]; found {
+			if info == nil {
+				// We have a cycle and use check.cycle to report it.
+				// We are guaranteed that check.cycle also finds the
+				// cycle because when infoFromTypeLit is called, any
+				// tname that's already in check.interfaces was also
+				// added to the path. (But the converse is not true:
+				// A non-nil tname is always the last element in path.)
+				ok := check.cycle(tname, path, true)
+				assert(ok)
+			}
+			return
+		}
+		check.interfaces[tname] = nil // computation started but not complete
+	}
+
+	if iface.Methods.List == nil {
+		// fast track for empty interface
+		info = &emptyIfaceInfo
+	} else {
+		// (syntactically) non-empty interface
+		info = new(ifaceInfo)
+
+		// collect explicitly declared methods and embedded interfaces
+		var mset methodInfoSet
+		var embeddeds []*ifaceInfo
+		var positions []token.Pos // entries correspond to positions of embeddeds; used for error reporting
+		for _, f := range iface.Methods.List {
+			if len(f.Names) > 0 {
+				// We have a method with name f.Names[0].
+				// (The parser ensures that there's only one method
+				// and we don't care if a constructed AST has more.)
+
+				// spec: "As with all method sets, in an interface type,
+				// each method must have a unique non-blank name."
+				if name := f.Names[0]; name.Name == "_" {
+					check.errorf(name.Pos(), "invalid method name _")
+					continue // ignore
+				}
+
+				m := &methodInfo{scope: scope, src: f}
+				if check.declareInMethodSet(&mset, f.Pos(), m) {
+					info.methods = append(info.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.
+				var e *ifaceInfo
+				switch ename := f.Type.(type) {
+				case *ast.Ident:
+					e = check.infoFromTypeName(scope, ename, path)
+				case *ast.SelectorExpr:
+					e = check.infoFromQualifiedTypeName(scope, ename)
+				default:
+					// The parser makes sure we only see one of the above.
+					// Constructed ASTs may contain other (invalid) nodes;
+					// we simply ignore them. The full type-checking pass
+					// will report those as errors later.
+				}
+				if e != nil {
+					embeddeds = append(embeddeds, e)
+					positions = append(positions, f.Type.Pos())
+				}
+			}
+		}
+		info.explicits = len(info.methods)
+
+		// collect methods of embedded interfaces
+		for i, e := range embeddeds {
+			pos := positions[i] // position of type name of embedded interface
+			for _, m := range e.methods {
+				if check.declareInMethodSet(&mset, pos, m) {
+					info.methods = append(info.methods, m)
+				}
+			}
+		}
+	}
+
+	// mark check.interfaces as complete
+	assert(info != nil)
+	if tname != nil {
+		check.interfaces[tname] = info
+	}
+
+	return
+}
+
+// infoFromTypeName computes the method set for the given type name
+// which must denote a type whose underlying type is an interface.
+// The same result qualifications apply as for infoFromTypeLit.
+// infoFromTypeName should only be called from infoFromTypeLit.
+func (check *Checker) infoFromTypeName(scope *Scope, name *ast.Ident, path []*TypeName) *ifaceInfo {
+	// A single call of infoFromTypeName handles a sequence of (possibly
+	// recursive) type declarations connected via unqualified type names.
+	// Each type declaration leading to another typename causes a "tail call"
+	// (goto) of this function. The general scenario looks like this:
+	//
+	//      ...
+	//      type Pn T        // previous declarations leading to T, path = [..., Pn]
+	//      type T interface { T0; ... }  // T0 leads to call of infoFromTypeName
+	//
+	//      // infoFromTypeName(name = T0, path = [..., Pn, T])
+	//      type T0 T1       // path = [..., Pn, T, T0]
+	//      type T1 T2  <-+  // path = [..., Pn, T, T0, T1]
+	//      type T2 ...   |  // path = [..., Pn, T, T0, T1, T2]
+	//      type Tn T1  --+  // path = [..., Pn, T, T0, T1, T2, Tn] and T1 is in path => cycle
+	//
+	// infoFromTypeName returns nil when such a cycle is detected. But in
+	// contrast to cycles involving interfaces, we must not report the
+	// error for "type name only" cycles because they will be found again
+	// during type-checking of embedded interfaces. Reporting those cycles
+	// here would lead to double reporting. Cycles involving embedding are
+	// not reported again later because type-checking of interfaces relies
+	// on the ifaceInfos computed here which are cycle-free by design.
+	//
+	// Remember the path length to detect "type name only" cycles.
+	start := len(path)
+
+typenameLoop:
+	// name must be a type name denoting a type whose underlying type is an interface
+	_, obj := scope.LookupParent(name.Name, check.pos)
+	if obj == nil {
+		return nil
+	}
+	tname, _ := obj.(*TypeName)
+	if tname == nil {
+		return nil
+	}
+
+	// We have a type name. It may be predeclared (error type),
+	// imported (dot import), or declared by a type declaration.
+	// It may not be an interface (e.g., predeclared type int).
+	// Resolve it by analyzing each possible case.
+
+	// Abort but don't report an error if we have a "type name only"
+	// cycle (see big function comment).
+	if check.cycle(tname, path[start:], false) {
+		return nil
+	}
+
+	// Abort and report an error if we have a general cycle.
+	if check.cycle(tname, path, true) {
+		return nil
+	}
+
+	path = append(path, tname)
+
+	// If tname is a package-level type declaration, it must be
+	// in the objMap. Follow the RHS of that declaration if so.
+	// The RHS may be a literal type (likely case), or another
+	// (possibly parenthesized and/or qualified) type name.
+	// (The declaration may be an alias declaration, but it
+	// doesn't matter for the purpose of determining the under-
+	// lying interface.)
+	if decl := check.objMap[tname]; decl != nil {
+		switch typ := unparen(decl.typ).(type) {
+		case *ast.Ident:
+			// type tname T
+			name = typ
+			goto typenameLoop
+		case *ast.SelectorExpr:
+			// type tname p.T
+			return check.infoFromQualifiedTypeName(decl.file, typ)
+		case *ast.InterfaceType:
+			// type tname interface{...}
+			return check.infoFromTypeLit(decl.file, typ, tname, path)
+		}
+		// type tname X // and X is not an interface type
+		return nil
+	}
+
+	// If tname is not a package-level declaration, in a well-typed
+	// program it should be a predeclared (error type), imported (dot
+	// import), or function local declaration. Either way, it should
+	// have been fully declared before use, except if there is a direct
+	// cycle, and direct cycles will be caught above. Also, the denoted
+	// type should be an interface (e.g., int is not an interface).
+	if typ := tname.typ; typ != nil {
+		// typ should be an interface
+		if ityp, _ := typ.Underlying().(*Interface); ityp != nil {
+			return infoFromType(ityp)
+		}
+	}
+
+	// In all other cases we have some error.
+	return nil
+}
+
+// infoFromQualifiedTypeName computes the method set for the given qualified type name, or nil.
+func (check *Checker) infoFromQualifiedTypeName(scope *Scope, qname *ast.SelectorExpr) *ifaceInfo {
+	// see also Checker.selector
+	name, _ := qname.X.(*ast.Ident)
+	if name == nil {
+		return nil
+	}
+	_, obj1 := scope.LookupParent(name.Name, check.pos)
+	if obj1 == nil {
+		return nil
+	}
+	pname, _ := obj1.(*PkgName)
+	if pname == nil {
+		return nil
+	}
+	assert(pname.pkg == check.pkg)
+	obj2 := pname.imported.scope.Lookup(qname.Sel.Name)
+	if obj2 == nil || !obj2.Exported() {
+		return nil
+	}
+	tname, _ := obj2.(*TypeName)
+	if tname == nil {
+		return nil
+	}
+	ityp, _ := tname.typ.Underlying().(*Interface)
+	if ityp == nil {
+		return nil
+	}
+	return infoFromType(ityp)
+}
+
+// infoFromType computes the method set for the given interface type.
+// The result is never nil.
+func infoFromType(typ *Interface) *ifaceInfo {
+	assert(typ.allMethods != nil) // typ must be completely set up
+
+	// fast track for empty interface
+	n := len(typ.allMethods)
+	if n == 0 {
+		return &emptyIfaceInfo
+	}
+
+	info := new(ifaceInfo)
+	info.explicits = len(typ.methods)
+	info.methods = make([]*methodInfo, n)
+
+	// If there are no embedded interfaces, simply collect the
+	// explicitly declared methods (optimization of common case).
+	if len(typ.methods) == n {
+		for i, m := range typ.methods {
+			info.methods[i] = &methodInfo{fun: m}
+		}
+		return info
+	}
+
+	// Interface types have a separate list for explicitly declared methods
+	// which shares its methods with the list of all (explicitly declared or
+	// embedded) methods. Collect all methods in a set so we can separate
+	// the embedded methods from the explicitly declared ones.
+	all := make(map[*Func]bool, n)
+	for _, m := range typ.allMethods {
+		all[m] = true
+	}
+	assert(len(all) == n) // methods must be unique
+
+	// collect explicitly declared methods
+	info.methods = make([]*methodInfo, n)
+	for i, m := range typ.methods {
+		info.methods[i] = &methodInfo{fun: m}
+		delete(all, m)
+	}
+
+	// collect remaining (embedded) methods
+	i := len(typ.methods)
+	for m := range all {
+		info.methods[i] = &methodInfo{fun: m}
+		i++
+	}
+	assert(i == n)
+
+	return info
+}
diff --git a/libgo/go/go/types/issues_test.go b/libgo/go/go/types/issues_test.go
index 81c00f9901f..6e0d4063f32 100644
--- a/libgo/go/go/types/issues_test.go
+++ b/libgo/go/go/types/issues_test.go
@@ -316,3 +316,44 @@ func TestIssue22525(t *testing.T) {
 		t.Errorf("got: %swant: %s", got, want)
 	}
 }
+
+func TestIssue25627(t *testing.T) {
+	const prefix = `package p; import "unsafe"; type P *struct{}; type I interface{}; type T `
+	// The src strings (without prefix) are constructed such that the number of semicolons
+	// plus one corresponds to the number of fields expected in the respective struct.
+	for _, src := range []string{
+		`struct { x Missing }`,
+		`struct { Missing }`,
+		`struct { *Missing }`,
+		`struct { unsafe.Pointer }`,
+		`struct { P }`,
+		`struct { *I }`,
+		`struct { a int; b Missing; *Missing }`,
+	} {
+		f, err := parser.ParseFile(fset, "", prefix+src, 0)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		cfg := Config{Importer: importer.Default(), Error: func(err error) {}}
+		info := &Info{Types: make(map[ast.Expr]TypeAndValue)}
+		_, err = cfg.Check(f.Name.Name, fset, []*ast.File{f}, info)
+		if err != nil {
+			if _, ok := err.(Error); !ok {
+				t.Fatal(err)
+			}
+		}
+
+		ast.Inspect(f, func(n ast.Node) bool {
+			if spec, _ := n.(*ast.TypeSpec); spec != nil {
+				if tv, ok := info.Types[spec.Type]; ok && spec.Name.Name == "T" {
+					want := strings.Count(src, ";") + 1
+					if got := tv.Type.(*Struct).NumFields(); got != want {
+						t.Errorf("%s: got %d fields; want %d", src, got, want)
+					}
+				}
+			}
+			return true
+		})
+	}
+}
diff --git a/libgo/go/go/types/lookup.go b/libgo/go/go/types/lookup.go
index ee8202d9e42..f31ef9cfe94 100644
--- a/libgo/go/go/types/lookup.go
+++ b/libgo/go/go/types/lookup.go
@@ -19,7 +19,7 @@ package types
 //	2) the list of all methods (method set) of an interface type; or
 //	3) the list of fields of a struct type.
 //
-// The earlier index entries are the indices of the anonymous struct fields
+// The earlier index entries are the indices of the embedded struct fields
 // traversed to get to the found entry, starting at depth 0.
 //
 // If no entry is found, a nil object is returned. In this case, the returned
@@ -149,7 +149,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
 					// T is a type name. If e.typ appeared multiple times at
 					// this depth, f.typ appears multiple times at the next
 					// depth.
-					if obj == nil && f.anonymous {
+					if obj == nil && f.embedded {
 						typ, isPtr := deref(f.typ)
 						// TODO(gri) optimization: ignore types that can't
 						// have fields or methods (only Named, Struct, and
diff --git a/libgo/go/go/types/methodset.go b/libgo/go/go/types/methodset.go
index 2a8b1c24f7a..2b810da7283 100644
--- a/libgo/go/go/types/methodset.go
+++ b/libgo/go/go/types/methodset.go
@@ -7,9 +7,9 @@
 package types
 
 import (
-	"bytes"
 	"fmt"
 	"sort"
+	"strings"
 )
 
 // A MethodSet is an ordered set of concrete or abstract (interface) methods;
@@ -24,7 +24,7 @@ func (s *MethodSet) String() string {
 		return "MethodSet {}"
 	}
 
-	var buf bytes.Buffer
+	var buf strings.Builder
 	fmt.Fprintln(&buf, "MethodSet {")
 	for _, f := range s.list {
 		fmt.Fprintf(&buf, "\t%s\n", f)
@@ -132,7 +132,7 @@ func NewMethodSet(T Type) *MethodSet {
 					// T is a type name. If typ appeared multiple times at
 					// this depth, f.Type appears multiple times at the next
 					// depth.
-					if f.anonymous {
+					if f.embedded {
 						typ, isPtr := deref(f.typ)
 						// TODO(gri) optimization: ignore types that can't
 						// have fields or methods (only Named, Struct, and
diff --git a/libgo/go/go/types/object.go b/libgo/go/go/types/object.go
index 633d32712ae..07adfbc34c3 100644
--- a/libgo/go/go/types/object.go
+++ b/libgo/go/go/types/object.go
@@ -34,9 +34,15 @@ type Object interface {
 	// 0 for all other objects (including objects in file scopes).
 	order() uint32
 
+	// color returns the object's color.
+	color() color
+
 	// setOrder sets the order number of the object. It must be > 0.
 	setOrder(uint32)
 
+	// setColor sets the object's color. It must not be white.
+	setColor(color color)
+
 	// setParent sets the parent scope of the object.
 	setParent(*Scope)
 
@@ -78,22 +84,74 @@ type object struct {
 	name      string
 	typ       Type
 	order_    uint32
+	color_    color
 	scopePos_ token.Pos
 }
 
-func (obj *object) Parent() *Scope      { return obj.parent }
-func (obj *object) Pos() token.Pos      { return obj.pos }
-func (obj *object) Pkg() *Package       { return obj.pkg }
-func (obj *object) Name() string        { return obj.name }
-func (obj *object) Type() Type          { return obj.typ }
-func (obj *object) Exported() bool      { return ast.IsExported(obj.name) }
-func (obj *object) Id() string          { return Id(obj.pkg, obj.name) }
+// color encodes the color of an object (see Checker.objDecl for details).
+type color uint32
+
+// An object may be painted in one of three colors.
+// Color values other than white or black are considered grey.
+const (
+	white color = iota
+	black
+	grey // must be > white and black
+)
+
+func (c color) String() string {
+	switch c {
+	case white:
+		return "white"
+	case black:
+		return "black"
+	default:
+		return "grey"
+	}
+}
+
+// colorFor returns the (initial) color for an object depending on
+// whether its type t is known or not.
+func colorFor(t Type) color {
+	if t != nil {
+		return black
+	}
+	return white
+}
+
+// Parent returns the scope in which the object is declared.
+// The result is nil for methods and struct fields.
+func (obj *object) Parent() *Scope { return obj.parent }
+
+// Pos returns the declaration position of the object's identifier.
+func (obj *object) Pos() token.Pos { return obj.pos }
+
+// Pkg returns the package to which the object belongs.
+// The result is nil for labels and objects in the Universe scope.
+func (obj *object) Pkg() *Package { return obj.pkg }
+
+// Name returns the object's (package-local, unqualified) name.
+func (obj *object) Name() string { return obj.name }
+
+// Type returns the object's type.
+func (obj *object) Type() Type { return obj.typ }
+
+// Exported reports whether the object is exported (starts with a capital letter).
+// It doesn't take into account whether the object is in a local (function) scope
+// or not.
+func (obj *object) Exported() bool { return ast.IsExported(obj.name) }
+
+// Id is a wrapper for Id(obj.Pkg(), obj.Name()).
+func (obj *object) Id() string { return Id(obj.pkg, obj.name) }
+
 func (obj *object) String() string      { panic("abstract") }
 func (obj *object) order() uint32       { return obj.order_ }
+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) 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 }
 
 func (obj *object) sameId(pkg *Package, name string) bool {
@@ -129,7 +187,7 @@ type PkgName struct {
 // NewPkgName returns a new PkgName object representing an imported package.
 // The remaining arguments set the attributes found with all Objects.
 func NewPkgName(pos token.Pos, pkg *Package, name string, imported *Package) *PkgName {
-	return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, token.NoPos}, imported, false}
+	return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, black, token.NoPos}, imported, false}
 }
 
 // Imported returns the package that was imported.
@@ -139,20 +197,21 @@ func (obj *PkgName) Imported() *Package { return obj.imported }
 // A Const represents a declared constant.
 type Const struct {
 	object
-	val     constant.Value
-	visited bool // for initialization cycle detection
+	val constant.Value
 }
 
 // NewConst returns a new constant with value val.
 // The remaining arguments set the attributes found with all Objects.
 func NewConst(pos token.Pos, pkg *Package, name string, typ Type, val constant.Value) *Const {
-	return &Const{object{nil, pos, pkg, name, typ, 0, token.NoPos}, val, false}
+	return &Const{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, val}
 }
 
+// Val returns the constant's value.
 func (obj *Const) Val() constant.Value { return obj.val }
-func (*Const) isDependency()           {} // a constant may be a dependency of an initialization expression
 
-// A TypeName represents a name for a (named or alias) type.
+func (*Const) isDependency() {} // a constant may be a dependency of an initialization expression
+
+// A TypeName represents a name for a (defined or alias) type.
 type TypeName struct {
 	object
 }
@@ -165,7 +224,7 @@ type TypeName struct {
 // argument for NewNamed, which will set the TypeName's type as a side-
 // effect.
 func NewTypeName(pos token.Pos, pkg *Package, name string, typ Type) *TypeName {
-	return &TypeName{object{nil, pos, pkg, name, typ, 0, token.NoPos}}
+	return &TypeName{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}}
 }
 
 // IsAlias reports whether obj is an alias name for a type.
@@ -195,32 +254,35 @@ func (obj *TypeName) IsAlias() bool {
 // A Variable represents a declared variable (including function parameters and results, and struct fields).
 type Var struct {
 	object
-	anonymous bool // if set, the variable is an anonymous struct field, and name is the type name
-	visited   bool // for initialization cycle detection
-	isField   bool // var is struct field
-	used      bool // set if the variable was used
+	embedded bool // if set, the variable is an embedded struct field, and name is the type name
+	isField  bool // var is struct field
+	used     bool // set if the variable was used
 }
 
 // NewVar returns a new variable.
 // The arguments set the attributes found with all Objects.
 func NewVar(pos token.Pos, pkg *Package, name string, typ Type) *Var {
-	return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}}
+	return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}}
 }
 
 // NewParam returns a new variable representing a function parameter.
 func NewParam(pos token.Pos, pkg *Package, name string, typ Type) *Var {
-	return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, used: true} // parameters are always 'used'
+	return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, used: true} // parameters are always 'used'
 }
 
 // NewField returns a new variable representing a struct field.
-// For anonymous (embedded) fields, the name is the unqualified
-// type name under which the field is accessible.
-func NewField(pos token.Pos, pkg *Package, name string, typ Type, anonymous bool) *Var {
-	return &Var{object: object{nil, pos, pkg, name, typ, 0, token.NoPos}, anonymous: anonymous, isField: true}
+// For embedded fields, the name is the unqualified type name
+/// under which the field is accessible.
+func NewField(pos token.Pos, pkg *Package, name string, typ Type, embedded bool) *Var {
+	return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}, embedded: embedded, isField: true}
 }
 
-// Anonymous reports whether the variable is an anonymous field.
-func (obj *Var) Anonymous() bool { return obj.anonymous }
+// Anonymous reports whether the variable is an embedded field.
+// Same as Embedded; only present for backward-compatibility.
+func (obj *Var) Anonymous() bool { return obj.embedded }
+
+// Embedded reports whether the variable is an embedded field.
+func (obj *Var) Embedded() bool { return obj.embedded }
 
 // IsField reports whether the variable is a struct field.
 func (obj *Var) IsField() bool { return obj.isField }
@@ -242,7 +304,7 @@ func NewFunc(pos token.Pos, pkg *Package, name string, sig *Signature) *Func {
 	if sig != nil {
 		typ = sig
 	}
-	return &Func{object{nil, pos, pkg, name, typ, 0, token.NoPos}}
+	return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), token.NoPos}}
 }
 
 // FullName returns the package- or receiver-type-qualified name of
@@ -267,7 +329,7 @@ type Label struct {
 
 // NewLabel returns a new label.
 func NewLabel(pos token.Pos, pkg *Package, name string) *Label {
-	return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid]}, false}
+	return &Label{object{pos: pos, pkg: pkg, name: name, typ: Typ[Invalid], color_: black}, false}
 }
 
 // A Builtin represents a built-in function.
@@ -278,7 +340,7 @@ type Builtin struct {
 }
 
 func newBuiltin(id builtinId) *Builtin {
-	return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid]}, id}
+	return &Builtin{object{name: predeclaredFuncs[id].name, typ: Typ[Invalid], color_: black}, id}
 }
 
 // Nil represents the predeclared value nil.
diff --git a/libgo/go/go/types/object_test.go b/libgo/go/go/types/object_test.go
index 9f073944182..88cd8757416 100644
--- a/libgo/go/go/types/object_test.go
+++ b/libgo/go/go/types/object_test.go
@@ -29,9 +29,9 @@ func TestIsAlias(t *testing.T) {
 		name  *TypeName
 		alias bool
 	}{
-		{NewTypeName(0, nil, "t0", nil), false}, // no type yet
-		{NewTypeName(0, pkg, "t0", nil), false}, // no type yet
-		{t1, false},                             // type name refers to named type and vice versa
+		{NewTypeName(0, nil, "t0", nil), false},            // no type yet
+		{NewTypeName(0, pkg, "t0", nil), false},            // no type yet
+		{t1, false},                                        // type name refers to named type and vice versa
 		{NewTypeName(0, nil, "t2", &emptyInterface), true}, // type name refers to unnamed type
 		{NewTypeName(0, pkg, "t3", n1), true},              // type name refers to named type with different type name
 		{NewTypeName(0, nil, "t4", Typ[Int32]), true},      // type name refers to basic type with different name
diff --git a/libgo/go/go/types/ordering.go b/libgo/go/go/types/ordering.go
deleted file mode 100644
index 3579abf7d7b..00000000000
--- a/libgo/go/go/types/ordering.go
+++ /dev/null
@@ -1,123 +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.
-
-// This file implements resolveOrder.
-
-package types
-
-import (
-	"go/ast"
-	"sort"
-)
-
-// resolveOrder computes the order in which package-level objects
-// must be type-checked.
-//
-// Interface types appear first in the list, sorted topologically
-// by dependencies on embedded interfaces that are also declared
-// in this package, followed by all other objects sorted in source
-// order.
-//
-// TODO(gri) Consider sorting all types by dependencies here, and
-// in the process check _and_ report type cycles. This may simplify
-// the full type-checking phase.
-//
-func (check *Checker) resolveOrder() []Object {
-	var ifaces, others []Object
-
-	// collect interface types with their dependencies, and all other objects
-	for obj := range check.objMap {
-		if ityp := check.interfaceFor(obj); ityp != nil {
-			ifaces = append(ifaces, obj)
-			// determine dependencies on embedded interfaces
-			for _, f := range ityp.Methods.List {
-				if len(f.Names) == 0 {
-					// Embedded interface: The type must be a (possibly
-					// qualified) identifier denoting another interface.
-					// Imported interfaces are already fully resolved,
-					// so we can ignore qualified identifiers.
-					if ident, _ := f.Type.(*ast.Ident); ident != nil {
-						embedded := check.pkg.scope.Lookup(ident.Name)
-						if check.interfaceFor(embedded) != nil {
-							check.objMap[obj].addDep(embedded)
-						}
-					}
-				}
-			}
-		} else {
-			others = append(others, obj)
-		}
-	}
-
-	// final object order
-	var order []Object
-
-	// sort interface types topologically by dependencies,
-	// and in source order if there are no dependencies
-	sort.Sort(inSourceOrder(ifaces))
-	visited := make(objSet)
-	for _, obj := range ifaces {
-		check.appendInPostOrder(&order, obj, visited)
-	}
-
-	// sort everything else in source order
-	sort.Sort(inSourceOrder(others))
-
-	return append(order, others...)
-}
-
-// interfaceFor returns the AST interface denoted by obj, or nil.
-func (check *Checker) interfaceFor(obj Object) *ast.InterfaceType {
-	tname, _ := obj.(*TypeName)
-	if tname == nil {
-		return nil // not a type
-	}
-	d := check.objMap[obj]
-	if d == nil {
-		check.dump("%s: %s should have been declared", obj.Pos(), obj.Name())
-		unreachable()
-	}
-	if d.typ == nil {
-		return nil // invalid AST - ignore (will be handled later)
-	}
-	ityp, _ := d.typ.(*ast.InterfaceType)
-	return ityp
-}
-
-func (check *Checker) appendInPostOrder(order *[]Object, obj Object, visited objSet) {
-	if visited[obj] {
-		// We've already seen this object; either because it's
-		// already added to order, or because we have a cycle.
-		// In both cases we stop. Cycle errors are reported
-		// when type-checking types.
-		return
-	}
-	visited[obj] = true
-
-	d := check.objMap[obj]
-	for _, obj := range orderedSetObjects(d.deps) {
-		check.appendInPostOrder(order, obj, visited)
-	}
-
-	*order = append(*order, obj)
-}
-
-func orderedSetObjects(set objSet) []Object {
-	list := make([]Object, len(set))
-	i := 0
-	for obj := range set {
-		// we don't care about the map element value
-		list[i] = obj
-		i++
-	}
-	sort.Sort(inSourceOrder(list))
-	return list
-}
-
-// inSourceOrder implements the sort.Sort interface.
-type inSourceOrder []Object
-
-func (a inSourceOrder) Len() int           { return len(a) }
-func (a inSourceOrder) Less(i, j int) bool { return a[i].order() < a[j].order() }
-func (a inSourceOrder) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
diff --git a/libgo/go/go/types/predicates.go b/libgo/go/go/types/predicates.go
index 3aa4878cce2..46ad4e2dc40 100644
--- a/libgo/go/go/types/predicates.go
+++ b/libgo/go/go/types/predicates.go
@@ -150,7 +150,9 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
 		// Two array types are identical if they have identical element types
 		// and the same array length.
 		if y, ok := y.(*Array); ok {
-			return x.len == y.len && identical(x.elem, y.elem, cmpTags, p)
+			// 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) && identical(x.elem, y.elem, cmpTags, p)
 		}
 
 	case *Slice:
@@ -162,13 +164,13 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
 	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 anonymous fields are considered to have the same
+		// 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.anonymous != g.anonymous ||
+					if f.embedded != g.embedded ||
 						cmpTags && x.Tag(i) != y.Tag(i) ||
 						!f.sameId(g.pkg, g.name) ||
 						!identical(f.typ, g.typ, cmpTags, p) {
diff --git a/libgo/go/go/types/resolver.go b/libgo/go/go/types/resolver.go
index d03c1799af9..5cbaba187b9 100644
--- a/libgo/go/go/types/resolver.go
+++ b/libgo/go/go/types/resolver.go
@@ -9,6 +9,7 @@ import (
 	"go/ast"
 	"go/constant"
 	"go/token"
+	"sort"
 	"strconv"
 	"strings"
 	"unicode"
@@ -24,8 +25,6 @@ type declInfo struct {
 	alias bool          // type alias declaration
 
 	// The deps field tracks initialization expression dependencies.
-	// As a special (overloaded) case, it also tracks dependencies of
-	// interface types on embedded interfaces (see ordering.go).
 	deps objSet // lazily initialized
 }
 
@@ -216,6 +215,7 @@ func (check *Checker) collectObjects() {
 		pkgImports[imp] = true
 	}
 
+	var methods []*Func // list of methods with non-blank _ names
 	for fileNo, file := range check.files {
 		// The package identifier denotes the current package,
 		// but there is no corresponding package object.
@@ -411,20 +411,13 @@ func (check *Checker) collectObjects() {
 					}
 				} else {
 					// method
-					check.recordDef(d.Name, obj)
-					// Associate method with receiver base type name, if possible.
-					// Ignore methods that have an invalid receiver, or a blank _
-					// receiver name. They will be type-checked later, with regular
-					// functions.
-					if list := d.Recv.List; len(list) > 0 {
-						typ := unparen(list[0].Type)
-						if ptr, _ := typ.(*ast.StarExpr); ptr != nil {
-							typ = unparen(ptr.X)
-						}
-						if base, _ := typ.(*ast.Ident); base != nil && base.Name != "_" {
-							check.assocMethod(base.Name, obj)
-						}
+					// (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)
 					}
+					check.recordDef(d.Name, obj)
 				}
 				info := &declInfo{file: fileScope, fdecl: d}
 				check.objMap[obj] = info
@@ -451,10 +444,90 @@ func (check *Checker) collectObjects() {
 			}
 		}
 	}
+
+	// Now that we have all package scope objects and all methods,
+	// associate methods with receiver base type name where possible.
+	// Ignore methods that have an invalid receiver. They will be
+	// type-checked later, with regular functions.
+	if methods == nil {
+		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
+			// receiver may be of the form T or *T, possibly with parentheses
+			typ := unparen(list[0].Type)
+			if ptr, _ := typ.(*ast.StarExpr); ptr != nil {
+				typ = unparen(ptr.X)
+			}
+			if base, _ := typ.(*ast.Ident); base != nil {
+				// base is a potential base type name; determine
+				// "underlying" defined type and associate f with it
+				if tname := check.resolveBaseTypeName(base); tname != nil {
+					check.methods[tname] = append(check.methods[tname], f)
+				}
+			}
+		}
+	}
 }
 
-// packageObjects typechecks all package objects in objList, but not function bodies.
-func (check *Checker) packageObjects(objList []Object) {
+// resolveBaseTypeName returns the non-alias receiver base type name,
+// explicitly declared in the package scope, for the given receiver
+// type name; or nil.
+func (check *Checker) resolveBaseTypeName(name *ast.Ident) *TypeName {
+	var path []*TypeName
+	for {
+		// name must denote an object found in the current package scope
+		// (note that dot-imported objects are not in the package scope!)
+		obj := check.pkg.scope.Lookup(name.Name)
+		if obj == nil {
+			return nil
+		}
+		// the object must be a type name...
+		tname, _ := obj.(*TypeName)
+		if tname == nil {
+			return nil
+		}
+
+		// ... which we have not seen before
+		if check.cycle(tname, path, false) {
+			return nil
+		}
+
+		// 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 {
+			return tname
+		}
+
+		// Otherwise, if tdecl defined an alias for a (possibly parenthesized)
+		// type which is not an (unqualified) named type, we're done because
+		// receiver base types must be named types declared in this package.
+		typ := unparen(tdecl.typ) // a type may be parenthesized
+		name, _ = typ.(*ast.Ident)
+		if name == nil {
+			return nil
+		}
+
+		// continue resolving name
+		path = append(path, tname)
+	}
+}
+
+// packageObjects typechecks all package objects, but not function bodies.
+func (check *Checker) packageObjects() {
+	// process package objects in source order for reproducible results
+	objList := make([]Object, len(check.objMap))
+	i := 0
+	for obj := range check.objMap {
+		objList[i] = obj
+		i++
+	}
+	sort.Sort(inSourceOrder(objList))
+
 	// 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 {
@@ -476,10 +549,20 @@ func (check *Checker) packageObjects(objList []Object) {
 	check.methods = nil
 }
 
-// functionBodies typechecks all function bodies.
-func (check *Checker) functionBodies() {
-	for _, f := range check.funcs {
-		check.funcBody(f.decl, f.name, f.sig, f.body)
+// inSourceOrder implements the sort.Sort interface.
+type inSourceOrder []Object
+
+func (a inSourceOrder) Len() int           { return len(a) }
+func (a inSourceOrder) Less(i, j int) bool { return a[i].order() < a[j].order() }
+func (a inSourceOrder) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+
+// processDelayed processes all delayed actions pushed after top.
+func (check *Checker) processDelayed(top int) {
+	for len(check.delayed) > top {
+		i := len(check.delayed) - 1
+		f := check.delayed[i]
+		check.delayed = check.delayed[:i]
+		f() // may append to check.delayed
 	}
 }
 
diff --git a/libgo/go/go/types/return.go b/libgo/go/go/types/return.go
index 0c1447f89b3..2d34a70b98b 100644
--- a/libgo/go/go/types/return.go
+++ b/libgo/go/go/types/return.go
@@ -28,15 +28,9 @@ func (check *Checker) isTerminating(s ast.Stmt, label string) bool {
 		return check.isTerminating(s.Stmt, s.Label.Name)
 
 	case *ast.ExprStmt:
-		// the predeclared (possibly parenthesized) panic() function is terminating
-		if call, _ := unparen(s.X).(*ast.CallExpr); call != nil {
-			if id, _ := call.Fun.(*ast.Ident); id != nil {
-				if _, obj := check.scope.LookupParent(id.Name, token.NoPos); obj != nil {
-					if b, _ := obj.(*Builtin); b != nil && b.id == _Panic {
-						return true
-					}
-				}
-			}
+		// calling the predeclared (possibly parenthesized) panic() function is terminating
+		if call, ok := unparen(s.X).(*ast.CallExpr); ok && check.isPanic[call] {
+			return true
 		}
 
 	case *ast.ReturnStmt:
diff --git a/libgo/go/go/types/sizes.go b/libgo/go/go/types/sizes.go
index 13e2abb5def..300f5211f15 100644
--- a/libgo/go/go/types/sizes.go
+++ b/libgo/go/go/types/sizes.go
@@ -132,9 +132,10 @@ func (s *StdSizes) Sizeof(T Type) int64 {
 		}
 	case *Array:
 		n := t.len
-		if n == 0 {
+		if n <= 0 {
 			return 0
 		}
+		// n > 0
 		a := s.Alignof(t.elem)
 		z := s.Sizeof(t.elem)
 		return align(z, a)*(n-1) + z
@@ -166,6 +167,7 @@ var gcArchSizes = map[string]*StdSizes{
 	"mips64le": {8, 8},
 	"ppc64":    {8, 8},
 	"ppc64le":  {8, 8},
+	"riscv64":  {8, 8},
 	"s390x":    {8, 8},
 	"wasm":     {8, 8},
 	// When adding more architectures here,
@@ -177,7 +179,7 @@ var gcArchSizes = map[string]*StdSizes{
 //
 // Supported architectures for compiler "gc":
 // "386", "arm", "arm64", "amd64", "amd64p32", "mips", "mipsle",
-// "mips64", "mips64le", "ppc64", "ppc64le", "s390x", "wasm".
+// "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "wasm".
 func SizesFor(compiler, arch string) Sizes {
 	var m map[string]*StdSizes
 	switch compiler {
diff --git a/libgo/go/go/types/stdlib_test.go b/libgo/go/go/types/stdlib_test.go
index 39a3be86bf9..b2f31efba6b 100644
--- a/libgo/go/go/types/stdlib_test.go
+++ b/libgo/go/go/types/stdlib_test.go
@@ -179,6 +179,8 @@ func TestStdFixed(t *testing.T) {
 		"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
 	)
 }
 
diff --git a/libgo/go/go/types/stmt.go b/libgo/go/go/types/stmt.go
index 5221bcc7c12..abd9d05ef2a 100644
--- a/libgo/go/go/types/stmt.go
+++ b/libgo/go/go/types/stmt.go
@@ -7,20 +7,18 @@
 package types
 
 import (
-	"fmt"
 	"go/ast"
 	"go/constant"
 	"go/token"
 	"sort"
 )
 
-func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt) {
+func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *ast.BlockStmt, iota constant.Value) {
 	if trace {
-		if name == "" {
-			name = ""
-		}
-		fmt.Printf("--- %s: %s {\n", name, sig)
-		defer fmt.Println("--- ")
+		check.trace(body.Pos(), "--- %s: %s", name, sig)
+		defer func() {
+			check.trace(body.End(), "--- ")
+		}()
 	}
 
 	// set function scope extent
@@ -36,6 +34,7 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body
 	check.context = context{
 		decl:  decl,
 		scope: sig.scope,
+		iota:  iota,
 		sig:   sig,
 	}
 	check.indent = 0
@@ -52,8 +51,6 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body
 
 	// spec: "Implementation restriction: A compiler may make it illegal to
 	// declare a variable inside a function body if the variable is never used."
-	// (One could check each scope after use, but that distributes this check
-	// over several places because CloseScope is not always called explicitly.)
 	check.usage(sig.scope)
 }
 
@@ -72,7 +69,7 @@ func (check *Checker) usage(scope *Scope) {
 	}
 
 	for _, scope := range scope.children {
-		// Don't go inside closure scopes a second time;
+		// Don't go inside function literal scopes a second time;
 		// they are handled explicitly by funcBody.
 		if !scope.isFunc {
 			check.usage(scope)
@@ -294,10 +291,6 @@ L:
 
 // stmt typechecks statement s.
 func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
-	// statements cannot use iota in general
-	// (constant declarations set it explicitly)
-	assert(check.iota == nil)
-
 	// statements must end with the same top scope as they started with
 	if debug {
 		defer func(scope *Scope) {
@@ -309,6 +302,9 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
 		}(check.scope)
 	}
 
+	// process collected function literals before scope changes
+	defer check.processDelayed(len(check.delayed))
+
 	inner := ctxt &^ (fallthroughOk | finalSwitchCase)
 	switch s := s.(type) {
 	case *ast.BadStmt, *ast.EmptyStmt:
@@ -440,7 +436,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
 				// list in a "return" statement if a different entity (constant, type, or variable)
 				// with the same name as a result parameter is in scope at the place of the return."
 				for _, obj := range res.vars {
-					if _, alt := check.scope.LookupParent(obj.name, check.pos); alt != nil && alt != obj {
+					if alt := check.lookup(obj.name); alt != nil && alt != obj {
 						check.errorf(s.Pos(), "result parameter %s not in scope at return", obj.name)
 						check.errorf(alt.Pos(), "\tinner declaration of %s", obj)
 						// ok to continue
diff --git a/libgo/go/go/types/testdata/const0.src b/libgo/go/go/types/testdata/const0.src
index a61717887e0..19fb1bdbbee 100644
--- a/libgo/go/go/types/testdata/const0.src
+++ b/libgo/go/go/types/testdata/const0.src
@@ -6,6 +6,8 @@
 
 package const0
 
+import "unsafe"
+
 // constants declarations must be initialized by constants
 var x = 0
 const c0 = x /* ERROR "not constant" */
@@ -281,6 +283,45 @@ func _() {
 	_ = y
 }
 
+// iotas are usable inside closures in constant declarations (#22345)
+const (
+	_ = iota
+	_ = len([iota]byte{})
+	_ = unsafe.Sizeof(iota)
+	_ = unsafe.Sizeof(func() { _ = iota })
+	_ = unsafe.Sizeof(func() { var _ = iota })
+	_ = unsafe.Sizeof(func() { const _ = iota })
+	_ = unsafe.Sizeof(func() { type _ [iota]byte })
+	_ = unsafe.Sizeof(func() { func() int { return iota }() })
+)
+
+// verify inner and outer const declarations have distinct iotas
+const (
+	zero = iota
+	one  = iota
+	_    = unsafe.Sizeof(func() {
+		var x [iota]int // [2]int
+		const (
+			Zero = iota
+			One
+			Two
+			_ = unsafe.Sizeof([iota-1]int{} == x) // assert types are equal
+			_ = unsafe.Sizeof([Two]int{} == x)    // assert types are equal
+		)
+	})
+	three = iota // the sequence continues
+)
+var _ [three]int = [3]int{} // assert 'three' has correct value
+
+var (
+	_ = iota /* ERROR "iota outside constant decl" */
+	_ = unsafe.Sizeof(iota  /* ERROR "iota outside constant decl" */ )
+	_ = unsafe.Sizeof(func() { _ = iota /* ERROR "iota outside constant decl" */ })
+	_ = unsafe.Sizeof(func() { var _ = iota /* ERROR "iota outside constant decl" */ })
+	_ = unsafe.Sizeof(func() { type _ [iota /* ERROR "iota outside constant decl" */ ]byte })
+	_ = unsafe.Sizeof(func() { func() int { return iota /* ERROR "iota outside constant decl" */ }() })
+)
+
 // constant arithmetic precision and rounding must lead to expected (integer) results
 var _ = []int64{
 	0.0005 * 1e9,
diff --git a/libgo/go/go/types/testdata/constdecl.src b/libgo/go/go/types/testdata/constdecl.src
index 6de9b13d6ef..c2f40ed6e67 100644
--- a/libgo/go/go/types/testdata/constdecl.src
+++ b/libgo/go/go/types/testdata/constdecl.src
@@ -5,6 +5,7 @@
 package constdecl
 
 import "math"
+import "unsafe"
 
 var v int
 
@@ -94,4 +95,16 @@ func _() {
 	)
 }
 
+// Test case for constants depending on function literals (see also #22992).
+const A /* ERROR initialization cycle */ = unsafe.Sizeof(func() { _ = A })
+
+func _() {
+	// The function literal below must not see a.
+	const a = unsafe.Sizeof(func() { _ = a /* ERROR "undeclared name" */ })
+	const b = unsafe.Sizeof(func() { _ = a })
+
+	// The function literal below must not see x, y, or z.
+	const x, y, z = 0, 1, unsafe.Sizeof(func() { _ = x /* ERROR "undeclared name" */ + y /* ERROR "undeclared name" */ + z /* ERROR "undeclared name" */ })
+}
+
 // TODO(gri) move extra tests from testdata/const0.src into here
diff --git a/libgo/go/go/types/testdata/cycles.src b/libgo/go/go/types/testdata/cycles.src
index b4bd5d8b157..59f112dba1d 100644
--- a/libgo/go/go/types/testdata/cycles.src
+++ b/libgo/go/go/types/testdata/cycles.src
@@ -4,6 +4,8 @@
 
 package cycles
 
+import "unsafe"
+
 type (
 	T0 int
 	T1 /* ERROR cycle */ T1
@@ -52,9 +54,9 @@ type (
 	// interfaces
 	I0 /* ERROR cycle */ interface{ I0 }
 
-	I1 interface{ I2 }
+	I1 /* ERROR cycle */ interface{ I2 }
 	I2 interface{ I3 }
-	I3 /* ERROR cycle */ interface{ I1 }
+	I3 interface{ I1 }
 
 	I4 interface{ f(I4) }
 
@@ -145,8 +147,17 @@ type (
 // test cases for issue 18643
 // (type cycle detection when non-type expressions are involved)
 type (
-	T14 [len(T14 /* ERROR cycle */ {})]int
+	T14 /* ERROR cycle */ [len(T14{})]int
 	T15 [][len(T15 /* ERROR cycle */ {})]int
 	T16 map[[len(T16 /* ERROR cycle */ {1:2})]int]int
 	T17 map[int][len(T17 /* ERROR cycle */ {1:2})]int
 )
+
+// Test case for types depending on function literals (see also #22992).
+type T20 chan [unsafe.Sizeof(func(ch T20){ _ = <-ch })]byte
+type T22 = chan [unsafe.Sizeof(func(ch T20){ _ = <-ch })]byte
+
+func _() {
+	type T1 chan [unsafe.Sizeof(func(ch T1){ _ = <-ch })]byte
+	type T2 = chan [unsafe.Sizeof(func(ch T2){ _ = <-ch })]byte
+}
diff --git a/libgo/go/go/types/testdata/cycles2.src b/libgo/go/go/types/testdata/cycles2.src
index 345ab56ea69..a7f4bc60f5b 100644
--- a/libgo/go/go/types/testdata/cycles2.src
+++ b/libgo/go/go/types/testdata/cycles2.src
@@ -69,47 +69,38 @@ type T interface {
 
 // Variations of this test case.
 
-type T1 interface {
-	m() [x1 /* ERROR no value */ .m()[0]]int
+type T1 /* ERROR cycle */ interface {
+	m() [x1.m()[0]]int
 }
 
 var x1 T1
 
-type T2 interface {
-	m() [len(x2 /* ERROR no value */ .m())]int
+type T2 /* ERROR cycle */ interface {
+	m() [len(x2.m())]int
 }
 
 var x2 T2
 
-type T3 interface {
+type T3 /* ERROR cycle */ interface {
 	m() [unsafe.Sizeof(x3.m)]int
 }
 
 var x3 T3
 
-// The test case below should also report an error for
-// the cast inside the T4 interface (like it does for the
-// variable initialization). The reason why it does not is
-// that inside T4, the method x4.m depends on T4 which is not
-// fully set up yet. The x4.m method happens to have an empty
-// signature which is why the cast is permitted.
-// TODO(gri) Consider marking methods as incomplete and provide
-// a better error message in that case.
-
-type T4 interface {
+type T4 /* ERROR cycle */ interface {
 	m() [unsafe.Sizeof(cast4(x4.m))]int
 }
 
 var x4 T4
-var _ = cast4(x4 /* ERROR cannot convert */.m)
+var _ = cast4(x4.m)
 
 type cast4 func()
 
 // This test is symmetric to the T4 case: Here the cast is
 // "correct", but it doesn't work inside the T5 interface.
 
-type T5 interface {
-	m() [unsafe.Sizeof(cast5(x5 /* ERROR cannot convert */ .m))]int
+type T5 /* ERROR cycle */ interface {
+	m() [unsafe.Sizeof(cast5(x5.m))]int
 }
 
 var x5 T5
diff --git a/libgo/go/go/types/testdata/cycles3.src b/libgo/go/go/types/testdata/cycles3.src
index 3da4fb5761a..5e89b627f00 100644
--- a/libgo/go/go/types/testdata/cycles3.src
+++ b/libgo/go/go/types/testdata/cycles3.src
@@ -48,7 +48,7 @@ type (
 )
 
 type (
-	U interface {
+	U /* ERROR cycle */ interface {
 		V
 	}
 
diff --git a/libgo/go/go/types/testdata/cycles4.src b/libgo/go/go/types/testdata/cycles4.src
index 3f6304be6be..445babca68b 100644
--- a/libgo/go/go/types/testdata/cycles4.src
+++ b/libgo/go/go/types/testdata/cycles4.src
@@ -108,15 +108,3 @@ type Element interface {
 type Event interface {
 	Target() Element
 }
-
-// Recognize issue #13895.
-
-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)
\ No newline at end of file
diff --git a/libgo/go/go/types/testdata/decls0.src b/libgo/go/go/types/testdata/decls0.src
index d4df386b132..162dfeda04e 100644
--- a/libgo/go/go/types/testdata/decls0.src
+++ b/libgo/go/go/types/testdata/decls0.src
@@ -61,7 +61,7 @@ type (
 
 
 type (
-	p1 pi /* ERROR "no field or method foo" */ .foo
+	p1 pi.foo /* ERROR "no field or method foo" */
 	p2 unsafe.Pointer
 )
 
@@ -97,7 +97,7 @@ type (
 		u, v, a /* ERROR "redeclared" */ float32
 	}
 	S2 struct {
-		S0 // anonymous field
+		S0 // embedded field
 		S0 /* ERROR "redeclared" */ int
 	}
 	S3 struct {
@@ -159,13 +159,13 @@ type (
 	I8 /* ERROR "illegal cycle" */ interface {
 		I8
 	}
-	I9 interface {
+	I9 /* ERROR "illegal cycle" */ interface {
 		I10
 	}
 	I10 interface {
 		I11
 	}
-	I11 /* ERROR "illegal cycle" */ interface {
+	I11 interface {
 		I9
 	}
 
@@ -184,15 +184,15 @@ type (
 
 // cycles in function/method declarations
 // (test cases for issue 5217 and variants)
-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 }
+func f1 /* ERROR cycle */ (x f1 /* ERROR "not a type" */ ) {}
+func f2 /* ERROR cycle */ (x *f2 /* ERROR "not a type" */ ) {}
+func f3 /* ERROR cycle */ () (x f3 /* ERROR "not a type" */ ) { return }
+func f4 /* ERROR cycle */ () (x *f4 /* ERROR "not a type" */ ) { return }
 
-func (S0) m1(x S0 /* ERROR "field or method" */ .m1) {}
-func (S0) m2(x *S0 /* ERROR "field or method" */ .m2) {}
-func (S0) m3() (x S0 /* ERROR "field or method" */ .m3) { return }
-func (S0) m4() (x *S0 /* ERROR "field or method" */ .m4) { return }
+func (S0) m1(x S0.m1 /* ERROR "field or method" */ ) {}
+func (S0) m2(x *S0.m2 /* ERROR "field or method" */ ) {}
+func (S0) m3() (x S0.m3 /* ERROR "field or method" */ ) { return }
+func (S0) m4() (x *S0.m4 /* ERROR "field or method" */ ) { 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/decls1.src
index 1ef28067645..07405469a44 100644
--- a/libgo/go/go/types/testdata/decls1.src
+++ b/libgo/go/go/types/testdata/decls1.src
@@ -64,7 +64,7 @@ var (
 	t13 int = a /* ERROR "shifted operand" */ << d
 	t14 int = i << j /* ERROR "must be unsigned" */
 	t15 math /* ERROR "not in selector" */
-	t16 math /* ERROR "not declared" */ .xxx
+	t16 math.xxx /* ERROR "not declared" */
 	t17 math /* ERROR "not a type" */ .Pi
 	t18 float64 = math.Pi * 10.0
 	t19 int = t1 /* ERROR "cannot call" */ ()
diff --git a/libgo/go/go/types/testdata/decls3.src b/libgo/go/go/types/testdata/decls3.src
index 80d2bc8ff8e..18ddf5859c6 100644
--- a/libgo/go/go/types/testdata/decls3.src
+++ b/libgo/go/go/types/testdata/decls3.src
@@ -19,7 +19,7 @@ func _() {
 	)
 
 	var t T3
-	_ = t /* ERROR "ambiguous selector" */ .X
+	_ = t.X /* ERROR "ambiguous selector" */
 }
 
 func _() {
@@ -31,7 +31,7 @@ func _() {
 	)
 
 	var t T4
-	_ = t /* ERROR "ambiguous selector" */ .X
+	_ = t.X /* ERROR "ambiguous selector" */
 }
 
 func issue4355() {
@@ -41,10 +41,10 @@ func issue4355() {
 	    T3 struct {T2}
 	    T4 struct {T2}
 	    T5 struct {T3; T4} // X is embedded twice at the same level via T3->T2->T1->X, T4->T2->T1->X
-	)	
+	)
 
 	var t T5
-	_ = t /* ERROR "ambiguous selector" */ .X
+	_ = t.X /* ERROR "ambiguous selector" */
 }
 
 func _() {
@@ -54,7 +54,7 @@ func _() {
 	type T struct{ A; B }
 
 	var t T
-	_ = t /* ERROR "ambiguous selector" */ .State
+	_ = t.State /* ERROR "ambiguous selector" */
 }
 
 // Embedded fields can be predeclared types.
@@ -99,9 +99,9 @@ func _() {
 	// unsafe.Pointers are treated like regular pointers when embedded
 	type T2 struct {
 		unsafe /* ERROR "cannot be unsafe.Pointer" */ .Pointer
-		*/* ERROR "cannot be unsafe.Pointer" */ unsafe.Pointer
+		*/* ERROR "cannot be unsafe.Pointer" */ /* ERROR "Pointer redeclared" */ unsafe.Pointer
 		UP /* ERROR "cannot be unsafe.Pointer" */
-		* /* ERROR "cannot be unsafe.Pointer" */ UP
+		* /* ERROR "cannot be unsafe.Pointer" */  /* ERROR "UP redeclared" */ UP
 	}
 }
 
@@ -118,8 +118,8 @@ func _() {
 
 	var p P
 	_ = p.x
-	_ = p /* ERROR "no field or method" */ .m
-	_ = P /* ERROR "no field or method" */ .m
+	_ = p.m /* ERROR "no field or method" */
+	_ = P.m /* ERROR "no field or method" */
 }
 
 // Borrowed from the FieldByName test cases in reflect/all_test.go.
@@ -209,9 +209,9 @@ type S13 struct {
 }
 
 func _() {
-	_ = struct /* ERROR "no field or method" */ {}{}.Foo
+	_ = struct{}{}.Foo /* ERROR "no field or method" */
 	_ = S0{}.A
-	_ = S0 /* ERROR "no field or method" */ {}.D
+	_ = S0{}.D /* ERROR "no field or method" */
 	_ = S1{}.A
 	_ = S1{}.B
 	_ = S1{}.S0
@@ -220,17 +220,17 @@ func _() {
 	_ = S2{}.S1
 	_ = S2{}.B
 	_ = S2{}.C
-	_ = S2 /* ERROR "no field or method" */ {}.D
-	_ = S3 /* ERROR "ambiguous selector" */ {}.S1
+	_ = S2{}.D /* ERROR "no field or method" */
+	_ = S3{}.S1 /* ERROR "ambiguous selector" */
 	_ = S3{}.A
-	_ = S3 /* ERROR "ambiguous selector" */ {}.B
+	_ = S3{}.B /* ERROR "ambiguous selector" */
 	_ = S3{}.D
 	_ = S3{}.E
 	_ = S4{}.A
-	_ = S4 /* ERROR "no field or method" */ {}.B
-	_ = S5 /* ERROR "ambiguous selector" */ {}.X
+	_ = S4{}.B /* ERROR "no field or method" */
+	_ = S5{}.X /* ERROR "ambiguous selector" */
 	_ = S5{}.Y
-	_ = S10 /* ERROR "ambiguous selector" */ {}.X
+	_ = S10{}.X /* ERROR "ambiguous selector" */
 	_ = S10{}.Y
 }
 
@@ -306,4 +306,4 @@ type R22 R21
 type R23 R21
 type R24 R21
 
-var _ = R0 /* ERROR "ambiguous selector" */ {}.X
\ No newline at end of file
+var _ = R0{}.X /* ERROR "ambiguous selector" */
\ No newline at end of file
diff --git a/libgo/go/go/types/testdata/errors.src b/libgo/go/go/types/testdata/errors.src
index 29fcd8fe1da..ff929217c4c 100644
--- a/libgo/go/go/types/testdata/errors.src
+++ b/libgo/go/go/types/testdata/errors.src
@@ -53,3 +53,8 @@ func _() {
 // Use unqualified names for package-local objects.
 type T struct{}
 var _ int = T /* ERROR value of type T */ {} // use T in error message rather then errors.T
+
+// Don't report errors containing "invalid type" (issue #24182).
+func _(x *missing /* ERROR undeclared name: missing */ ) {
+	x.m() // there shouldn't be an error here referring to *invalid type
+}
diff --git a/libgo/go/go/types/testdata/expr3.src b/libgo/go/go/types/testdata/expr3.src
index b7ab9b38c75..b4c81633246 100644
--- a/libgo/go/go/types/testdata/expr3.src
+++ b/libgo/go/go/types/testdata/expr3.src
@@ -153,17 +153,17 @@ type T struct {
 func (*T) m() {}
 
 func method_expressions() {
-	_ = T /* ERROR "no field or method" */ .a
-	_ = T /* ERROR "has no method" */ .x
-	_ = T /* ERROR "not in method set" */ .m
+	_ = T.a /* ERROR "no field or method" */
+	_ = T.x /* ERROR "has no method" */
+	_ = T.m /* ERROR "not in method set" */
 	_ = (*T).m
 
-	var f func(*T) = T /* ERROR "not in method set" */ .m
+	var f func(*T) = T.m /* ERROR "not in method set" */
 	var g func(*T) = (*T).m
 	_, _ = f, g
 
-	_ = T /* ERROR "has no method" */ .y
-	_ = ( /* ERROR "has no method" */ *T).y
+	_ = T.y /* ERROR "has no method" */
+	_ = (*T).y /* ERROR "has no method" */
 }
 
 func struct_literals() {
diff --git a/libgo/go/go/types/testdata/importC.src b/libgo/go/go/types/testdata/importC.src
index f50f7f33d3e..f55be2d5c53 100644
--- a/libgo/go/go/types/testdata/importC.src
+++ b/libgo/go/go/types/testdata/importC.src
@@ -20,7 +20,7 @@ type T struct {
 	Ordinal int
 }
 
-func f(args []T) {
+func _(args []T) {
 	var s string
 	for i, v := range args {
 		cname := C.CString(v.Name)
@@ -33,3 +33,22 @@ type CType C.Type
 
 const _ CType = C.X // no error due to invalid constant type
 const _ = C.X
+
+// Test cases extracted from issue #23712.
+
+func _() {
+	var a [C.ArrayLength]byte
+	_ = a[0] // no index out of bounds error here
+}
+
+// Additional tests to verify fix for #23712.
+
+func _() {
+	var a [C.ArrayLength1]byte
+	_ = 1 / len(a) // no division by zero error here and below
+	_ = 1 / cap(a)
+	_ = uint(unsafe.Sizeof(a)) // must not be negative
+
+	var b [C.ArrayLength2]byte
+	a = b // should be valid
+}
diff --git a/libgo/go/go/types/testdata/importdecl0a.src b/libgo/go/go/types/testdata/importdecl0a.src
index 463dcd083dd..e96fca3cdd5 100644
--- a/libgo/go/go/types/testdata/importdecl0a.src
+++ b/libgo/go/go/types/testdata/importdecl0a.src
@@ -32,7 +32,7 @@ import f2 "fmt"
 
 // reflect.flag must not be visible in this package
 type flag int
-type _ reflect /* ERROR "not exported" */ .flag
+type _ reflect.flag /* ERROR "not exported" */
 
 // imported package name may conflict with local objects
 type reflect /* ERROR "reflect already declared" */ int
diff --git a/libgo/go/go/types/testdata/importdecl1a.src b/libgo/go/go/types/testdata/importdecl1a.src
index 8301820dda9..d377c01638a 100644
--- a/libgo/go/go/types/testdata/importdecl1a.src
+++ b/libgo/go/go/types/testdata/importdecl1a.src
@@ -6,6 +6,17 @@
 
 package importdecl1
 
+import "go/ast"
 import . "unsafe"
 
 var _ Pointer // use dot-imported package unsafe
+
+// Test cases for issue 23914.
+
+type A interface {
+	// Methods m1, m2 must be type-checked in this file scope
+	// even when embedded in an interface in a different
+	// file of the same package.
+	m1() ast.Node
+	m2() Pointer
+}
diff --git a/libgo/go/go/types/testdata/importdecl1b.src b/libgo/go/go/types/testdata/importdecl1b.src
index f24bb9ade97..ee70bbd8e73 100644
--- a/libgo/go/go/types/testdata/importdecl1b.src
+++ b/libgo/go/go/types/testdata/importdecl1b.src
@@ -5,3 +5,7 @@
 package importdecl1
 
 import . /* ERROR "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/init0.src
index ef0349c70f5..6e8746afb64 100644
--- a/libgo/go/go/types/testdata/init0.src
+++ b/libgo/go/go/types/testdata/init0.src
@@ -75,7 +75,7 @@ var x8 = x7
 func f2() (int, int) { return f3() + f3(), 0 }
 func f3() int { return x8 }
 
-// cycles via closures
+// cycles via function literals
 
 var x9 /* ERROR initialization cycle */ = func() int { return x9 }()
 
diff --git a/libgo/go/go/types/testdata/issues.src b/libgo/go/go/types/testdata/issues.src
index 8729555e175..d85e04e68cb 100644
--- a/libgo/go/go/types/testdata/issues.src
+++ b/libgo/go/go/types/testdata/issues.src
@@ -84,7 +84,7 @@ func issue10979() {
 		nosuchtype /* ERROR undeclared name: nosuchtype */
 	}
 	type _ interface {
-		fmt /* ERROR Nosuchtype not declared by package fmt */ .Nosuchtype
+		fmt.Nosuchtype /* ERROR Nosuchtype not declared by package fmt */
 	}
 	type _ interface {
 		nosuchpkg /* ERROR undeclared name: nosuchpkg */ .Nosuchtype
@@ -207,3 +207,90 @@ func issue20358() {
 	_ = T{t}
 	_ = P{f: p}
 }
+
+// Test that we don't declare lhs variables in short variable
+// declarations before we type-check function literals on the
+// rhs.
+func issue24026() {
+	f := func() int { f(0) /* must refer to outer f */; return 0 }
+	_ = f
+
+	_ = func() {
+		f := func() { _ = f() /* must refer to outer f */ }
+		_ = f
+	}
+
+	// b and c must not be visible inside function literal
+	a := 0
+	a, b, c := func() (int, int, int) {
+		return a, b /* ERROR undeclared */ , c /* ERROR undeclared */
+	}()
+	_, _ = b, c
+}
+
+func f(int) {} // for issue24026
+
+// Test that we don't report a "missing return statement" error
+// (due to incorrect context when type-checking interfaces).
+func issue24140(x interface{}) int {
+        switch x.(type) {
+        case interface{}:
+                return 0
+        default:
+                panic(0)
+        }
+}
+
+// Test that we don't crash when the 'if' condition is missing.
+func issue25438() {
+	if { /* ERROR missing condition */ }
+	if x := 0; /* ERROR missing condition */ { _ = x }
+	if
+	{ /* ERROR missing condition */ }
+}
+
+// Test that we can embed alias type names in interfaces.
+type issue25301 interface {
+	E
+}
+
+type E = interface {
+	m()
+}
+
+// Test case from issue. Eventually we may disallow this due
+// to the cycle via the alias type name. But for now we make
+// sure this is accepted.
+type issue25301b = interface {
+	m() interface{ issue25301b }
+}
+
+type issue25301c interface {
+	notE // ERROR struct\{\} is not an interface
+}
+
+type notE = struct{}
+
+// Test that method declarations don't introduce artificial cycles
+// (issue #26124).
+const CC TT = 1
+type TT int
+func (TT) MM() [CC]TT
+
+// Reduced test case from issue #26124.
+const preloadLimit LNumber = 128
+type LNumber float64
+func (LNumber) assertFunction() *LFunction
+type LFunction struct {
+	GFunction LGFunction
+}
+type LGFunction func(*LState)
+type LState struct {
+	reg *registry
+}
+type registry struct {
+	alloc *allocator
+}
+type allocator struct {
+	_ [int(preloadLimit)]int
+}
diff --git a/libgo/go/go/types/testdata/methodsets.src b/libgo/go/go/types/testdata/methodsets.src
index 89211468ead..2f21faf1e48 100644
--- a/libgo/go/go/types/testdata/methodsets.src
+++ b/libgo/go/go/types/testdata/methodsets.src
@@ -29,7 +29,7 @@ type T3 struct {
 func _() {
 	var (
 		_ func(T0) = T0.v0
-		_ = T0 /* ERROR "not in method set" */ .p0
+		_ = T0.p0 /* ERROR "not in method set" */
 
 		_ func (*T0) = (*T0).v0
 		_ func (*T0) = (*T0).p0
@@ -40,7 +40,7 @@ func _() {
 		_ func(T2) = T2.p2
 
 		_ func(T3) = T3.v0
-		_ func(T3) = T3 /* ERROR "not in method set" */ .p0
+		_ func(T3) = T3.p0 /* ERROR "not in method set" */
 		_ func(T3) = T3.v1
 		_ func(T3) = T3.p1
 		_ func(T3) = T3.v2
@@ -135,7 +135,7 @@ func _() {
 func _() {
 	var (
 		_ func() = T0{}.v0
-		_ func() = T0 /* ERROR "not in method set" */ {}.p0
+		_ func() = T0{}.p0 /* ERROR "not in method set" */
 
 		_ func() = (&T0{}).v0
 		_ func() = (&T0{}).p0
@@ -145,7 +145,7 @@ func _() {
 		// no values for T2
 
 		_ func() = T3{}.v0
-		_ func() = T3 /* ERROR "not in method set" */ {}.p0
+		_ func() = T3{}.p0 /* ERROR "not in method set" */
 		_ func() = T3{}.v1
 		_ func() = T3{}.p1
 		_ func() = T3{}.v2
@@ -163,7 +163,7 @@ func _() {
 // Method calls with value receivers
 func _() {
 	T0{}.v0()
-	T0 /* ERROR "not in method set" */ {}.p0()
+	T0{}.p0 /* ERROR "not in method set" */ ()
 
 	(&T0{}).v0()
 	(&T0{}).p0()
@@ -173,7 +173,7 @@ func _() {
 	// no values for T2
 
 	T3{}.v0()
-	T3 /* ERROR "not in method set" */ {}.p0()
+	T3{}.p0 /* ERROR "not in method set" */ ()
 	T3{}.v1()
 	T3{}.p1()
 	T3{}.v2()
@@ -196,9 +196,9 @@ func issue5918() {
 		_ func(error) string = error.Error
 
 		perr = &err
-		_ = perr /* ERROR "no field or method" */ .Error()
-		_ func() string = perr /* ERROR "no field or method" */ .Error
-		_ func(*error) string = ( /* ERROR "no field or method" */ *error).Error
+		_ = perr.Error /* ERROR "no field or method" */ ()
+		_ func() string = perr.Error /* ERROR "no field or method" */
+		_ func(*error) string = (*error).Error /* ERROR "no field or method" */
 	)
 
 	type T *interface{ m() int }
@@ -207,8 +207,8 @@ func issue5918() {
 		_ = (*x).m()
 		_ = (*x).m
 
-		_ = x /* ERROR "no field or method" */ .m()
-		_ = x /* ERROR "no field or method" */ .m
-		_ = T /* ERROR "no field or method" */ .m
+		_ = x.m /* ERROR "no field or method" */ ()
+		_ = x.m /* ERROR "no field or method" */
+		_ = T.m /* ERROR "no field or method" */
 	)
 }
diff --git a/libgo/go/go/types/testdata/stmt1.src b/libgo/go/go/types/testdata/stmt1.src
index 24ad6ebdf18..f79f92058bb 100644
--- a/libgo/go/go/types/testdata/stmt1.src
+++ b/libgo/go/go/types/testdata/stmt1.src
@@ -239,3 +239,21 @@ L:	select {
 	}
 	; ; ;
 } /* ERROR "missing return" */
+
+func parenPanic() int {
+	((((((panic)))(0))))
+}
+
+func issue23218a() int {
+	{
+		panic := func(interface{}){}
+		panic(0)
+	}
+} /* ERROR "missing return" */
+
+func issue23218b() int {
+	{
+		panic := func(interface{}){}
+		((((panic))))(0)
+	}
+} /* ERROR "missing return" */
diff --git a/libgo/go/go/types/testdata/vardecl.src b/libgo/go/go/types/testdata/vardecl.src
index 197dec2d5dc..54f5ef1e10d 100644
--- a/libgo/go/go/types/testdata/vardecl.src
+++ b/libgo/go/go/types/testdata/vardecl.src
@@ -151,7 +151,7 @@ func (r T) _(a, b, c int) (u, v, w int) {
 	return
 }
 
-// Unused variables in closures must lead to only one error (issue #22524).
+// Unused variables in function literals must lead to only one error (issue #22524).
 func _() {
 	_ = func() {
 		var x /* ERROR declared but not used */ int
@@ -190,4 +190,17 @@ func _() {
 	_ = b
 }
 
+// Test case for variables depending on function literals (see also #22992).
+var A /* ERROR initialization cycle */ = func() int { return A }()
+
+func _() {
+	// The function literal below must not see a.
+	var a = func() int { return a /* ERROR "undeclared name" */ }()
+	var _ = func() int { return a }()
+
+	// The function literal below must not see x, y, or z.
+	var x, y, z = 0, 1, func() int { return x /* ERROR "undeclared name" */ + y /* ERROR "undeclared name" */ + z /* ERROR "undeclared name" */ }()
+	_, _, _ = x, y, z
+}
+
 // TODO(gri) consolidate other var decl checks in this file
\ No newline at end of file
diff --git a/libgo/go/go/types/type.go b/libgo/go/go/types/type.go
index a58684a535f..d9399a6587c 100644
--- a/libgo/go/go/types/type.go
+++ b/libgo/go/go/types/type.go
@@ -97,9 +97,11 @@ 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} }
 
 // Len returns the length of array a.
+// A negative result indicates an unknown length.
 func (a *Array) Len() int64 { return a.len }
 
 // Elem returns element type of array a.
@@ -139,7 +141,7 @@ func NewStruct(fields []*Var, tags []string) *Struct {
 	return &Struct{fields: fields, tags: tags}
 }
 
-// NumFields returns the number of fields in the struct (including blank and anonymous fields).
+// NumFields returns the number of fields in the struct (including blank and embedded fields).
 func (s *Struct) NumFields() int { return len(s.fields) }
 
 // Field returns the i'th field for 0 <= i < NumFields().
@@ -240,8 +242,8 @@ func (s *Signature) Variadic() bool { return s.variadic }
 
 // An Interface represents an interface type.
 type Interface struct {
-	methods   []*Func  // ordered list of explicitly declared methods
-	embeddeds []*Named // ordered list of explicitly embedded types
+	methods   []*Func // ordered list of explicitly declared methods
+	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)
 }
@@ -254,8 +256,28 @@ var emptyInterface = Interface{allMethods: markComplete}
 var markComplete = make([]*Func, 0)
 
 // NewInterface returns a new (incomplete) interface for the given methods and embedded types.
-// To compute the method set of the interface, Complete must be called.
+// Each embedded type must have an underlying type of interface type.
+// NewInterface takes ownership of the provided methods and may modify their types by setting
+// missing receivers. To compute the method set of the interface, Complete must be called.
+//
+// Deprecated: Use NewInterfaceType instead which allows any (even non-defined) interface types
+// to be embedded. This is necessary for interfaces that embed alias type names referring to
+// non-defined (literal) interface types.
 func NewInterface(methods []*Func, embeddeds []*Named) *Interface {
+	tnames := make([]Type, len(embeddeds))
+	for i, t := range embeddeds {
+		tnames[i] = t
+	}
+	return NewInterfaceType(methods, tnames)
+}
+
+// NewInterfaceType returns a new (incomplete) interface for the given methods and embedded types.
+// Each embedded type must have an underlying type of interface type (this property is not
+// verified for defined types, which may be in the process of being set up and which don't
+// have a valid underlying type yet).
+// NewInterfaceType takes ownership of the provided methods and may modify their types by setting
+// missing receivers. To compute the method set of the interface, Complete must be called.
+func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
 	typ := new(Interface)
 
 	if len(methods) == 0 && len(embeddeds) == 0 {
@@ -267,15 +289,24 @@ func NewInterface(methods []*Func, embeddeds []*Named) *Interface {
 		if mset.insert(m) != nil {
 			panic("multiple methods with the same name")
 		}
-		// set receiver
-		// TODO(gri) Ideally, we should use a named type here instead of
-		// typ, for less verbose printing of interface method signatures.
-		m.typ.(*Signature).recv = NewVar(m.pos, m.pkg, "", typ)
+		// set receiver if we don't have one
+		if sig := m.typ.(*Signature); sig.recv == nil {
+			sig.recv = NewVar(m.pos, m.pkg, "", typ)
+		}
 	}
 	sort.Sort(byUniqueMethodName(methods))
 
-	if embeddeds != nil {
-		sort.Sort(byUniqueTypeName(embeddeds))
+	if len(embeddeds) > 0 {
+		// All embedded types should be interfaces; however, defined types
+		// may not yet be fully resolved. Only verify that non-defined types
+		// are interfaces. This matches the behavior of the code before the
+		// fix for #25301 (issue #25596).
+		for _, t := range embeddeds {
+			if _, ok := t.(*Named); !ok && !IsInterface(t) {
+				panic("embedded type is not an interface")
+			}
+		}
+		sort.Stable(byUniqueTypeName(embeddeds))
 	}
 
 	typ.methods = methods
@@ -293,9 +324,14 @@ func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] }
 // NumEmbeddeds returns the number of embedded types in interface t.
 func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) }
 
-// Embedded returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds().
-// The types are ordered by the corresponding TypeName's unique Id.
-func (t *Interface) Embedded(i int) *Named { return t.embeddeds[i] }
+// Embedded returns the i'th embedded defined (*Named) type of interface t for 0 <= i < t.NumEmbeddeds().
+// The result is nil if the i'th embedded type is not a defined type.
+//
+// Deprecated: Use EmbeddedType which is not restricted to defined (*Named) types.
+func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named); return tname }
+
+// EmbeddedType returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds().
+func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] }
 
 // NumMethods returns the total number of methods of interface t.
 func (t *Interface) NumMethods() int { return len(t.allMethods) }
@@ -308,36 +344,33 @@ func (t *Interface) Method(i int) *Func { return t.allMethods[i] }
 func (t *Interface) Empty() bool { return len(t.allMethods) == 0 }
 
 // Complete computes the interface's method set. It must be called by users of
-// NewInterface after the interface's embedded types are fully defined and
-// before using the interface type in any way other than to form other types.
-// Complete returns the receiver.
+// NewInterfaceType and NewInterface after the interface's embedded types are
+// fully defined and before using the interface type in any way other than to
+// form other types. Complete returns the receiver.
 func (t *Interface) Complete() *Interface {
 	if t.allMethods != nil {
 		return t
 	}
 
 	var allMethods []*Func
-	if t.embeddeds == nil {
-		if t.methods == nil {
-			allMethods = make([]*Func, 0, 1)
-		} else {
-			allMethods = t.methods
+	allMethods = append(allMethods, t.methods...)
+	for _, et := range t.embeddeds {
+		it := et.Underlying().(*Interface)
+		it.Complete()
+		for _, tm := range it.allMethods {
+			// Make a copy of the method and adjust its receiver type.
+			newm := *tm
+			newmtyp := *tm.typ.(*Signature)
+			newm.typ = &newmtyp
+			newmtyp.recv = NewVar(newm.pos, newm.pkg, "", t)
+			allMethods = append(allMethods, &newm)
 		}
-	} else {
-		allMethods = append(allMethods, t.methods...)
-		for _, et := range t.embeddeds {
-			it := et.Underlying().(*Interface)
-			it.Complete()
-			for _, tm := range it.allMethods {
-				// Make a copy of the method and adjust its receiver type.
-				newm := *tm
-				newmtyp := *tm.typ.(*Signature)
-				newm.typ = &newmtyp
-				newmtyp.recv = NewVar(newm.pos, newm.pkg, "", t)
-				allMethods = append(allMethods, &newm)
-			}
-		}
-		sort.Sort(byUniqueMethodName(allMethods))
+	}
+	sort.Sort(byUniqueMethodName(allMethods))
+
+	// t.methods and/or t.embeddeds may have been empty
+	if allMethods == nil {
+		allMethods = markComplete
 	}
 	t.allMethods = allMethods
 
@@ -437,26 +470,26 @@ func (t *Named) AddMethod(m *Func) {
 
 // Implementations for Type methods.
 
-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 (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 (t *Signature) Underlying() Type { return t }
+func (s *Signature) Underlying() Type { return s }
 func (t *Interface) Underlying() Type { return t }
-func (t *Map) Underlying() Type       { return t }
-func (t *Chan) 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 (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 (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 (t *Signature) 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 (t *Map) String() string       { return TypeString(t, nil) }
-func (t *Chan) 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) }
diff --git a/libgo/go/go/types/typestring.go b/libgo/go/go/types/typestring.go
index a9c0bfde1f9..0c007f6cd01 100644
--- a/libgo/go/go/types/typestring.go
+++ b/libgo/go/go/types/typestring.go
@@ -121,7 +121,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
 			if i > 0 {
 				buf.WriteString("; ")
 			}
-			if !f.anonymous {
+			if !f.embedded {
 				buf.WriteString(f.name)
 				buf.WriteByte(' ')
 			}
@@ -146,7 +146,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
 	case *Interface:
 		// We write the source-level methods and embedded types rather
 		// than the actual method set since resolved method signatures
-		// may have non-printable cycles if parameters have anonymous
+		// may have non-printable cycles if parameters have embedded
 		// interface types that (directly or indirectly) embed the
 		// current interface. For instance, consider the result type
 		// of m:
diff --git a/libgo/go/go/types/typestring_test.go b/libgo/go/go/types/typestring_test.go
index 640ffb1c2c7..3dd89d6d2ce 100644
--- a/libgo/go/go/types/typestring_test.go
+++ b/libgo/go/go/types/typestring_test.go
@@ -140,16 +140,41 @@ func TestTypeString(t *testing.T) {
 
 func TestIncompleteInterfaces(t *testing.T) {
 	sig := NewSignature(nil, nil, nil, false)
+	m := NewFunc(token.NoPos, nil, "m", sig)
 	for _, test := range []struct {
 		typ  *Interface
 		want string
 	}{
 		{new(Interface), "interface{/* incomplete */}"},
 		{new(Interface).Complete(), "interface{}"},
+
 		{NewInterface(nil, nil), "interface{/* incomplete */}"},
 		{NewInterface(nil, nil).Complete(), "interface{}"},
-		{NewInterface([]*Func{NewFunc(token.NoPos, nil, "m", sig)}, nil), "interface{m() /* incomplete */}"},
-		{NewInterface([]*Func{NewFunc(token.NoPos, nil, "m", sig)}, nil).Complete(), "interface{m()}"},
+		{NewInterface([]*Func{}, nil), "interface{/* incomplete */}"},
+		{NewInterface([]*Func{}, nil).Complete(), "interface{}"},
+		{NewInterface(nil, []*Named{}), "interface{/* incomplete */}"},
+		{NewInterface(nil, []*Named{}).Complete(), "interface{}"},
+		{NewInterface([]*Func{m}, nil), "interface{m() /* incomplete */}"},
+		{NewInterface([]*Func{m}, nil).Complete(), "interface{m()}"},
+		{NewInterface(nil, []*Named{newDefined(new(Interface).Complete())}), "interface{T /* incomplete */}"},
+		{NewInterface(nil, []*Named{newDefined(new(Interface).Complete())}).Complete(), "interface{T}"},
+		{NewInterface(nil, []*Named{newDefined(NewInterface([]*Func{m}, nil))}), "interface{T /* incomplete */}"},
+		{NewInterface(nil, []*Named{newDefined(NewInterface([]*Func{m}, nil).Complete())}), "interface{T /* incomplete */}"},
+		{NewInterface(nil, []*Named{newDefined(NewInterface([]*Func{m}, nil).Complete())}).Complete(), "interface{T}"},
+
+		{NewInterfaceType(nil, nil), "interface{/* incomplete */}"},
+		{NewInterfaceType(nil, nil).Complete(), "interface{}"},
+		{NewInterfaceType([]*Func{}, nil), "interface{/* incomplete */}"},
+		{NewInterfaceType([]*Func{}, nil).Complete(), "interface{}"},
+		{NewInterfaceType(nil, []Type{}), "interface{/* incomplete */}"},
+		{NewInterfaceType(nil, []Type{}).Complete(), "interface{}"},
+		{NewInterfaceType([]*Func{m}, nil), "interface{m() /* incomplete */}"},
+		{NewInterfaceType([]*Func{m}, nil).Complete(), "interface{m()}"},
+		{NewInterfaceType(nil, []Type{new(Interface).Complete()}), "interface{interface{} /* incomplete */}"},
+		{NewInterfaceType(nil, []Type{new(Interface).Complete()}).Complete(), "interface{interface{}}"},
+		{NewInterfaceType(nil, []Type{NewInterfaceType([]*Func{m}, nil)}), "interface{interface{m() /* incomplete */} /* incomplete */}"},
+		{NewInterfaceType(nil, []Type{NewInterfaceType([]*Func{m}, nil).Complete()}), "interface{interface{m()} /* incomplete */}"},
+		{NewInterfaceType(nil, []Type{NewInterfaceType([]*Func{m}, nil).Complete()}).Complete(), "interface{interface{m()}}"},
 	} {
 		got := test.typ.String()
 		if got != test.want {
@@ -158,6 +183,13 @@ func TestIncompleteInterfaces(t *testing.T) {
 	}
 }
 
+// newDefined creates a new defined type named T with the given underlying type.
+// Helper function for use with TestIncompleteInterfaces only.
+func newDefined(underlying Type) *Named {
+	tname := NewTypeName(token.NoPos, nil, "T", nil)
+	return NewNamed(tname, underlying, nil)
+}
+
 func TestQualifiedTypeString(t *testing.T) {
 	t.Skip("skipping for gccgo--no importer")
 	p, _ := pkgFor("p.go", "package p; type T int", nil)
diff --git a/libgo/go/go/types/typexpr.go b/libgo/go/go/types/typexpr.go
index 92ab06b0f25..45ada5874bc 100644
--- a/libgo/go/go/types/typexpr.go
+++ b/libgo/go/go/types/typexpr.go
@@ -22,6 +22,8 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeNa
 	x.mode = invalid
 	x.expr = e
 
+	// Note that we cannot use check.lookup here because the returned scope
+	// may be different from obj.Parent(). See also Scope.LookupParent doc.
 	scope, obj := check.scope.LookupParent(e.Name, check.pos)
 	if obj == nil {
 		if e.Name == "_" {
@@ -69,21 +71,17 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeNa
 
 	case *TypeName:
 		x.mode = typexpr
-		// check for cycle
-		// (it's ok to iterate forward because each named type appears at most once in path)
-		for i, prev := range path {
-			if prev == obj {
-				check.errorf(obj.pos, "illegal cycle in declaration of %s", obj.name)
-				// print cycle
-				for _, obj := range path[i:] {
-					check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
-				}
-				check.errorf(obj.Pos(), "\t%s", obj.Name())
-				// maintain x.mode == typexpr despite error
-				typ = Typ[Invalid]
+		// package-level alias cycles are now checked by Checker.objDecl
+		if useCycleMarking {
+			if check.objMap[obj] != nil {
 				break
 			}
 		}
+		if check.cycle(obj, path, true) {
+			// maintain x.mode == typexpr despite error
+			typ = Typ[Invalid]
+			break
+		}
 
 	case *Var:
 		// It's ok to mark non-local variables, but ignore variables
@@ -116,11 +114,35 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, path []*TypeNa
 	x.typ = typ
 }
 
+// cycle reports whether obj appears in path or not.
+// If it does, and report is set, it also reports a cycle error.
+func (check *Checker) cycle(obj *TypeName, path []*TypeName, report bool) bool {
+	// (it's ok to iterate forward because each named type appears at most once in path)
+	for i, prev := range path {
+		if prev == obj {
+			if report {
+				check.errorf(obj.pos, "illegal cycle in declaration of %s", obj.name)
+				// print cycle
+				for _, obj := range path[i:] {
+					check.errorf(obj.Pos(), "\t%s refers to", obj.Name()) // secondary error, \t indented
+				}
+				check.errorf(obj.Pos(), "\t%s", obj.Name())
+			}
+			return true
+		}
+	}
+	return false
+}
+
 // typExpr type-checks the type expression e and returns its type, or Typ[Invalid].
 // If def != nil, e is the type specification for the named 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. Path contains the path of named types
-// referring to this type.
+// referring to this type; i.e. it is the path of named types directly containing
+// each other and leading to the current type e. Indirect containment (e.g. via
+// pointer indirection, function parameter, etc.) breaks the path (leads to a new
+// path, and usually via calling Checker.typ below) and those types are not found
+// in the path.
 //
 func (check *Checker) typExpr(e ast.Expr, def *Named, path []*TypeName) (T Type) {
 	if trace {
@@ -139,7 +161,18 @@ func (check *Checker) typExpr(e ast.Expr, def *Named, path []*TypeName) (T Type)
 	return
 }
 
+// typ is like typExpr (with a nil argument for the def parameter),
+// but typ breaks type cycles. It should be called for components of
+// types that break cycles, such as pointer base types, slice or map
+// element types, etc. See the comment in typExpr for details.
+//
 func (check *Checker) typ(e ast.Expr) Type {
+	// typExpr is called with a nil path indicating an indirection:
+	// push indir sentinel on object path
+	if useCycleMarking {
+		check.push(indir)
+		defer check.pop()
+	}
 	return check.typExpr(e, nil, nil)
 }
 
@@ -305,7 +338,7 @@ func (check *Checker) typExprInternal(e ast.Expr, def *Named, path []*TypeName)
 		//
 		// Delay this check because it requires fully setup types;
 		// it is safe to continue in any case (was issue 6667).
-		check.delay(func() {
+		check.later(func() {
 			if !Comparable(typ.key) {
 				check.errorf(e.Key.Pos(), "invalid map key type %s", typ.key)
 			}
@@ -368,6 +401,9 @@ func (check *Checker) typOrNil(e ast.Expr) Type {
 	return Typ[Invalid]
 }
 
+// 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).
 func (check *Checker) arrayLength(e ast.Expr) int64 {
 	var x operand
 	check.expr(&x, e)
@@ -375,7 +411,7 @@ func (check *Checker) arrayLength(e ast.Expr) int64 {
 		if x.mode != invalid {
 			check.errorf(x.pos(), "array length %s must be constant", &x)
 		}
-		return 0
+		return -1
 	}
 	if isUntyped(x.typ) || isInteger(x.typ) {
 		if val := constant.ToInt(x.val); val.Kind() == constant.Int {
@@ -384,12 +420,12 @@ func (check *Checker) arrayLength(e ast.Expr) int64 {
 					return n
 				}
 				check.errorf(x.pos(), "invalid array length %s", &x)
-				return 0
+				return -1
 			}
 		}
 	}
 	check.errorf(x.pos(), "array length %s must be integer", &x)
-	return 0
+	return -1
 }
 
 func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) {
@@ -456,44 +492,92 @@ func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool
 	return true
 }
 
-func (check *Checker) interfaceType(iface *Interface, ityp *ast.InterfaceType, def *Named, path []*TypeName) {
-	// empty interface: common case
-	if ityp.Methods == nil {
+func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named, path []*TypeName) {
+	// fast-track empty interface
+	if iface.Methods.List == nil {
+		ityp.allMethods = markComplete
 		return
 	}
 
-	// The parser ensures that field tags are nil and we don't
-	// care if a constructed AST contains non-nil tags.
+	// collect embedded interfaces
+	// Only needed for printing and API. Delay collection
+	// to end of type-checking (for package-global interfaces)
+	// when all types are complete. Local interfaces are handled
+	// after each statement (as each statement processes delayed
+	// functions).
+	interfaceContext := check.context // capture for use in closure below
+	check.later(func() {
+		if trace {
+			check.trace(iface.Pos(), "-- delayed checking embedded interfaces of %v", iface)
+			check.indent++
+			defer func() {
+				check.indent--
+			}()
+		}
+
+		// The context must be restored since for local interfaces
+		// delayed functions are processed after each statement
+		// (was issue #24140).
+		defer func(ctxt context) {
+			check.context = ctxt
+		}(check.context)
+		check.context = interfaceContext
+
+		for _, f := range iface.Methods.List {
+			if len(f.Names) == 0 {
+				typ := check.typ(f.Type)
+				// typ should be a named type denoting an interface
+				// (the parser will make sure it's a named type but
+				// constructed ASTs may be wrong).
+				if typ == Typ[Invalid] {
+					continue // error reported before
+				}
+				embed, _ := typ.Underlying().(*Interface)
+				if embed == nil {
+					check.errorf(f.Type.Pos(), "%s is not an interface", typ)
+					continue
+				}
+				// Correct embedded interfaces must be complete -
+				// don't just assert, but report error since this
+				// used to be the underlying cause for issue #18395.
+				if embed.allMethods == nil {
+					check.dump("%v: incomplete embedded interface %s", f.Type.Pos(), typ)
+					unreachable()
+				}
+				// collect interface
+				ityp.embeddeds = append(ityp.embeddeds, typ)
+			}
+		}
+		// sort to match NewInterface/NewInterface2
+		// TODO(gri) we may be able to switch to source order
+		sort.Stable(byUniqueTypeName(ityp.embeddeds))
+	})
+
+	// compute method set
+	var tname *TypeName
+	if def != nil {
+		tname = def.obj
+	}
+	info := check.infoFromTypeLit(check.scope, iface, tname, path)
+	if info == nil || info == &emptyIfaceInfo {
+		// error or empty interface - exit early
+		ityp.allMethods = markComplete
+		return
+	}
 
 	// use named receiver type if available (for better error messages)
-	var recvTyp Type = iface
+	var recvTyp Type = ityp
 	if def != nil {
 		recvTyp = def
 	}
 
-	// Phase 1: Collect explicitly declared methods, the corresponding
-	//          signature (AST) expressions, and the list of embedded
-	//          type (AST) expressions. Do not resolve signatures or
-	//          embedded types yet to avoid cycles referring to this
-	//          interface.
-
-	var (
-		mset       objset
-		signatures []ast.Expr // list of corresponding method signatures
-		embedded   []ast.Expr // list of embedded types
-	)
-	for _, f := range ityp.Methods.List {
-		if len(f.Names) > 0 {
-			// The parser ensures that there's only one method
-			// and we don't care if a constructed AST has more.
-			name := f.Names[0]
+	// collect methods
+	var sigfix []*methodInfo
+	for i, minfo := range info.methods {
+		fun := minfo.fun
+		if fun == nil {
+			name := minfo.src.Names[0]
 			pos := name.Pos()
-			// spec: "As with all method sets, in an interface type,
-			// each method must have a unique non-blank name."
-			if name.Name == "_" {
-				check.errorf(pos, "invalid method name _")
-				continue
-			}
 			// Don't type-check signature yet - use an
 			// empty signature now and update it later.
 			// Since we know the receiver, set it up now
@@ -504,101 +588,64 @@ func (check *Checker) interfaceType(iface *Interface, ityp *ast.InterfaceType, d
 			// also the T4 and T5 tests in testdata/cycles2.src.
 			sig := new(Signature)
 			sig.recv = NewVar(pos, check.pkg, "", recvTyp)
-			m := NewFunc(pos, check.pkg, name.Name, sig)
-			if check.declareInSet(&mset, pos, m) {
-				iface.methods = append(iface.methods, m)
-				iface.allMethods = append(iface.allMethods, m)
-				signatures = append(signatures, f.Type)
-				check.recordDef(name, m)
-			}
-		} else {
-			// embedded type
-			embedded = append(embedded, f.Type)
+			fun = NewFunc(pos, check.pkg, name.Name, sig)
+			minfo.fun = fun
+			check.recordDef(name, fun)
+			sigfix = append(sigfix, minfo)
 		}
+		// fun != nil
+		if i < info.explicits {
+			ityp.methods = append(ityp.methods, fun)
+		}
+		ityp.allMethods = append(ityp.allMethods, fun)
 	}
 
-	// Phase 2: Resolve embedded interfaces. Because an interface must not
-	//          embed itself (directly or indirectly), each embedded interface
-	//          can be fully resolved without depending on any method of this
-	//          interface (if there is a cycle or another error, the embedded
-	//          type resolves to an invalid type and is ignored).
-	//          In particular, the list of methods for each embedded interface
-	//          must be complete (it cannot depend on this interface), and so
-	//          those methods can be added to the list of all methods of this
-	//          interface.
-
-	for _, e := range embedded {
-		pos := e.Pos()
-		typ := check.typExpr(e, nil, path)
-		// Determine underlying embedded (possibly incomplete) type
-		// by following its forward chain.
-		named, _ := typ.(*Named)
-		under := underlying(named)
-		embed, _ := under.(*Interface)
-		if embed == nil {
-			if typ != Typ[Invalid] {
-				check.errorf(pos, "%s is not an interface", typ)
-			}
-			continue
-		}
-		iface.embeddeds = append(iface.embeddeds, named)
-		// collect embedded methods
-		if embed.allMethods == nil {
-			check.errorf(pos, "internal error: incomplete embedded interface %s (issue #18395)", named)
-		}
-		for _, m := range embed.allMethods {
-			if check.declareInSet(&mset, pos, m) {
-				iface.allMethods = append(iface.allMethods, m)
-			}
-		}
-	}
-
-	// Phase 3: At this point all methods have been collected for this interface.
-	//          It is now safe to type-check the signatures of all explicitly
-	//          declared methods, even if they refer to this interface via a cycle
-	//          and embed the methods of this interface in a parameter of interface
-	//          type.
-
-	for i, m := range iface.methods {
-		expr := signatures[i]
-		typ := check.typ(expr)
+	// fix signatures now that we have collected all methods
+	savedContext := check.context
+	for _, minfo := range sigfix {
+		// (possibly embedded) methods must be type-checked within their scope and
+		// type-checking them must not affect the current context (was issue #23914)
+		check.context = context{scope: minfo.scope}
+		typ := check.typ(minfo.src.Type)
 		sig, _ := typ.(*Signature)
 		if sig == nil {
 			if typ != Typ[Invalid] {
-				check.invalidAST(expr.Pos(), "%s is not a method signature", typ)
+				check.invalidAST(minfo.src.Type.Pos(), "%s is not a method signature", typ)
 			}
 			continue // keep method with empty method signature
 		}
 		// update signature, but keep recv that was set up before
-		old := m.typ.(*Signature)
+		old := minfo.fun.typ.(*Signature)
 		sig.recv = old.recv
-		*old = *sig // update signature (don't replace it!)
+		*old = *sig // update signature (don't replace pointer!)
 	}
+	check.context = savedContext
 
-	// TODO(gri) The list of explicit methods is only sorted for now to
-	// produce the same Interface as NewInterface. We may be able to
-	// claim source order in the future. Revisit.
-	sort.Sort(byUniqueMethodName(iface.methods))
+	// sort to match NewInterface/NewInterface2
+	// TODO(gri) we may be able to switch to source order
+	sort.Sort(byUniqueMethodName(ityp.methods))
 
-	// TODO(gri) The list of embedded types is only sorted for now to
-	// produce the same Interface as NewInterface. We may be able to
-	// claim source order in the future. Revisit.
-	sort.Sort(byUniqueTypeName(iface.embeddeds))
-
-	if iface.allMethods == nil {
-		iface.allMethods = make([]*Func, 0) // mark interface as complete
+	if ityp.allMethods == nil {
+		ityp.allMethods = markComplete
 	} else {
-		sort.Sort(byUniqueMethodName(iface.allMethods))
+		sort.Sort(byUniqueMethodName(ityp.allMethods))
 	}
 }
 
 // byUniqueTypeName named type lists can be sorted by their unique type names.
-type byUniqueTypeName []*Named
+type byUniqueTypeName []Type
 
 func (a byUniqueTypeName) Len() int           { return len(a) }
-func (a byUniqueTypeName) Less(i, j int) bool { return a[i].obj.Id() < a[j].obj.Id() }
+func (a byUniqueTypeName) Less(i, j int) bool { return sortName(a[i]) < sortName(a[j]) }
 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 {
+		return named.obj.Id()
+	}
+	return ""
+}
+
 // byUniqueMethodName method lists can be sorted by their unique method names.
 type byUniqueMethodName []*Func
 
@@ -634,7 +681,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
 	// current field typ and tag
 	var typ Type
 	var tag string
-	add := func(ident *ast.Ident, anonymous bool, pos token.Pos) {
+	add := func(ident *ast.Ident, embedded bool, pos token.Pos) {
 		if tag != "" && tags == nil {
 			tags = make([]string, len(fields))
 		}
@@ -643,7 +690,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
 		}
 
 		name := ident.Name
-		fld := NewField(pos, check.pkg, name, typ, anonymous)
+		fld := NewField(pos, check.pkg, name, typ, embedded)
 		// spec: "Within a struct, non-blank field names must be unique."
 		if name == "_" || check.declareInSet(&fset, pos, fld) {
 			fields = append(fields, fld)
@@ -651,6 +698,16 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
 		}
 	}
 
+	// addInvalid adds an embedded field of invalid type to the struct for
+	// fields with errors; this keeps the number of struct fields in sync
+	// with the source as long as the fields are _ or have different names
+	// (issue #25627).
+	addInvalid := func(ident *ast.Ident, pos token.Pos) {
+		typ = Typ[Invalid]
+		tag = ""
+		add(ident, true, pos)
+	}
+
 	for _, f := range list.List {
 		typ = check.typExpr(f.Type, nil, path)
 		tag = check.tag(f.Tag)
@@ -660,13 +717,16 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
 				add(name, false, name.Pos())
 			}
 		} else {
-			// anonymous field
+			// 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."
 			pos := f.Type.Pos()
-			name := anonymousFieldIdent(f.Type)
+			name := embeddedFieldIdent(f.Type)
 			if name == nil {
-				check.invalidAST(pos, "anonymous field type %s has no name", f.Type)
+				check.invalidAST(pos, "embedded field type %s has no name", f.Type)
+				name = ast.NewIdent("_")
+				name.NamePos = pos
+				addInvalid(name, pos)
 				continue
 			}
 			t, isPtr := deref(typ)
@@ -676,22 +736,26 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
 			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(pos, "anonymous field type cannot be unsafe.Pointer")
+					check.errorf(pos, "embedded field type cannot be unsafe.Pointer")
+					addInvalid(name, pos)
 					continue
 				}
 
 			case *Pointer:
-				check.errorf(pos, "anonymous field type cannot be a pointer")
+				check.errorf(pos, "embedded field type cannot be a pointer")
+				addInvalid(name, pos)
 				continue
 
 			case *Interface:
 				if isPtr {
-					check.errorf(pos, "anonymous field type cannot be a pointer to an interface")
+					check.errorf(pos, "embedded field type cannot be a pointer to an interface")
+					addInvalid(name, pos)
 					continue
 				}
 			}
@@ -703,17 +767,17 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType, path []*TypeNa
 	styp.tags = tags
 }
 
-func anonymousFieldIdent(e ast.Expr) *ast.Ident {
+func embeddedFieldIdent(e ast.Expr) *ast.Ident {
 	switch e := e.(type) {
 	case *ast.Ident:
 		return e
 	case *ast.StarExpr:
 		// *T is valid, but **T is not
 		if _, ok := e.X.(*ast.StarExpr); !ok {
-			return anonymousFieldIdent(e.X)
+			return embeddedFieldIdent(e.X)
 		}
 	case *ast.SelectorExpr:
 		return e.Sel
 	}
-	return nil // invalid anonymous field
+	return nil // invalid embedded field
 }
diff --git a/libgo/go/go/types/universe.go b/libgo/go/go/types/universe.go
index 07d7078ae25..7af6dab320e 100644
--- a/libgo/go/go/types/universe.go
+++ b/libgo/go/go/types/universe.go
@@ -12,9 +12,15 @@ import (
 	"strings"
 )
 
+// The Universe scope contains all predeclared objects of Go.
+// It is the outermost scope of any chain of nested scopes.
+var Universe *Scope
+
+// The Unsafe package is the package returned by an importer
+// for the import path "unsafe".
+var Unsafe *Package
+
 var (
-	Universe     *Scope
-	Unsafe       *Package
 	universeIota *Const
 	universeByte *Basic // uint8 alias, but has name "byte"
 	universeRune *Basic // int32 alias, but has name "rune"
@@ -74,7 +80,7 @@ func defPredeclaredTypes() {
 	res := NewVar(token.NoPos, nil, "", Typ[String])
 	sig := &Signature{results: NewTuple(res)}
 	err := NewFunc(token.NoPos, nil, "Error", sig)
-	typ := &Named{underlying: NewInterface([]*Func{err}, nil).Complete()}
+	typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil).Complete()}
 	sig.recv = NewVar(token.NoPos, nil, "", typ)
 	def(NewTypeName(token.NoPos, nil, "error", typ))
 }
@@ -96,7 +102,7 @@ func defPredeclaredConsts() {
 }
 
 func defPredeclaredNil() {
-	def(&Nil{object{name: "nil", typ: Typ[UntypedNil]}})
+	def(&Nil{object{name: "nil", typ: Typ[UntypedNil], color_: black}})
 }
 
 // A builtinId is the id of a builtin function.
@@ -201,6 +207,7 @@ func init() {
 // scope; other objects are inserted in the universe scope.
 //
 func def(obj Object) {
+	assert(obj.color() == black)
 	name := obj.Name()
 	if strings.Contains(name, " ") {
 		return // nothing to do
diff --git a/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305.go b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305.go
index 3f0dcb9d8cf..e28f49d12fc 100644
--- a/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305.go
+++ b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305.go
@@ -7,6 +7,7 @@ package chacha20poly1305 // import "golang.org/x/crypto/chacha20poly1305"
 
 import (
 	"crypto/cipher"
+	"encoding/binary"
 	"errors"
 )
 
@@ -18,7 +19,7 @@ const (
 )
 
 type chacha20poly1305 struct {
-	key [32]byte
+	key [8]uint32
 }
 
 // New returns a ChaCha20-Poly1305 AEAD that uses the given, 256-bit key.
@@ -27,7 +28,14 @@ func New(key []byte) (cipher.AEAD, error) {
 		return nil, errors.New("chacha20poly1305: bad key length")
 	}
 	ret := new(chacha20poly1305)
-	copy(ret.key[:], key)
+	ret.key[0] = binary.LittleEndian.Uint32(key[0:4])
+	ret.key[1] = binary.LittleEndian.Uint32(key[4:8])
+	ret.key[2] = binary.LittleEndian.Uint32(key[8:12])
+	ret.key[3] = binary.LittleEndian.Uint32(key[12:16])
+	ret.key[4] = binary.LittleEndian.Uint32(key[16:20])
+	ret.key[5] = binary.LittleEndian.Uint32(key[20:24])
+	ret.key[6] = binary.LittleEndian.Uint32(key[24:28])
+	ret.key[7] = binary.LittleEndian.Uint32(key[28:32])
 	return ret, nil
 }
 
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 1e523b9951b..4e7b6ea84f0 100644
--- a/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
+++ b/libgo/go/golang_org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go
@@ -6,7 +6,11 @@
 
 package chacha20poly1305
 
-import "encoding/binary"
+import (
+	"encoding/binary"
+
+	"internal/cpu"
+)
 
 //go:noescape
 func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
@@ -14,78 +18,27 @@ func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool
 //go:noescape
 func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte)
 
-// cpuid is implemented in chacha20poly1305_amd64.s.
-func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
-
-// xgetbv with ecx = 0 is implemented in chacha20poly1305_amd64.s.
-func xgetbv() (eax, edx uint32)
-
 var (
-	useASM  bool
-	useAVX2 bool
+	useASM  = cpu.X86.HasSSSE3
+	useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2
 )
 
-func init() {
-	detectCpuFeatures()
-}
-
-// detectCpuFeatures is used to detect if cpu instructions
-// used by the functions implemented in assembler in
-// chacha20poly1305_amd64.s are supported.
-func detectCpuFeatures() {
-	maxId, _, _, _ := cpuid(0, 0)
-	if maxId < 1 {
-		return
-	}
-
-	_, _, ecx1, _ := cpuid(1, 0)
-
-	haveSSSE3 := isSet(9, ecx1)
-	useASM = haveSSSE3
-
-	haveOSXSAVE := isSet(27, ecx1)
-
-	osSupportsAVX := false
-	// For XGETBV, OSXSAVE bit is required and sufficient.
-	if haveOSXSAVE {
-		eax, _ := xgetbv()
-		// Check if XMM and YMM registers have OS support.
-		osSupportsAVX = isSet(1, eax) && isSet(2, eax)
-	}
-	haveAVX := isSet(28, ecx1) && osSupportsAVX
-
-	if maxId < 7 {
-		return
-	}
-
-	_, ebx7, _, _ := cpuid(7, 0)
-	haveAVX2 := isSet(5, ebx7) && haveAVX
-	haveBMI2 := isSet(8, ebx7)
-
-	useAVX2 = haveAVX2 && haveBMI2
-}
-
-// isSet checks if bit at bitpos is set in value.
-func isSet(bitpos uint, value uint32) bool {
-	return value&(1< 0 {
+		copy(s.buf[len(s.buf)-64:], src[fin:])
+	}
+
+	// qr calculates a quarter round
+	qr := func(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
+		a += b
+		d ^= a
+		d = (d << 16) | (d >> 16)
+		c += d
+		b ^= c
+		b = (b << 12) | (b >> 20)
+		a += b
+		d ^= a
+		d = (d << 8) | (d >> 24)
+		c += d
+		b ^= c
+		b = (b << 7) | (b >> 25)
+		return a, b, c, d
+	}
+
+	// ChaCha20 constants
+	const (
+		j0 = 0x61707865
+		j1 = 0x3320646e
+		j2 = 0x79622d32
+		j3 = 0x6b206574
+	)
+
+	// pre-calculate most of the first round
+	s1, s5, s9, s13 := qr(j1, s.key[1], s.key[5], s.nonce[0])
+	s2, s6, s10, s14 := qr(j2, s.key[2], s.key[6], s.nonce[1])
+	s3, s7, s11, s15 := qr(j3, s.key[3], s.key[7], s.nonce[2])
+
+	n := len(src)
+	src, dst = src[:n:n], dst[:n:n] // BCE hint
+	for i := 0; i < n; i += 64 {
+		// calculate the remainder of the first round
+		s0, s4, s8, s12 := qr(j0, s.key[0], s.key[4], s.counter)
+
+		// execute the second round
+		x0, x5, x10, x15 := qr(s0, s5, s10, s15)
+		x1, x6, x11, x12 := qr(s1, s6, s11, s12)
+		x2, x7, x8, x13 := qr(s2, s7, s8, s13)
+		x3, x4, x9, x14 := qr(s3, s4, s9, s14)
+
+		// execute the remaining 18 rounds
+		for i := 0; i < 9; i++ {
+			x0, x4, x8, x12 = qr(x0, x4, x8, x12)
+			x1, x5, x9, x13 = qr(x1, x5, x9, x13)
+			x2, x6, x10, x14 = qr(x2, x6, x10, x14)
+			x3, x7, x11, x15 = qr(x3, x7, x11, x15)
+
+			x0, x5, x10, x15 = qr(x0, x5, x10, x15)
+			x1, x6, x11, x12 = qr(x1, x6, x11, x12)
+			x2, x7, x8, x13 = qr(x2, x7, x8, x13)
+			x3, x4, x9, x14 = qr(x3, x4, x9, x14)
+		}
+
+		x0 += j0
+		x1 += j1
+		x2 += j2
+		x3 += j3
+
+		x4 += s.key[0]
+		x5 += s.key[1]
+		x6 += s.key[2]
+		x7 += s.key[3]
+		x8 += s.key[4]
+		x9 += s.key[5]
+		x10 += s.key[6]
+		x11 += s.key[7]
+
+		x12 += s.counter
+		x13 += s.nonce[0]
+		x14 += s.nonce[1]
+		x15 += s.nonce[2]
+
+		// increment the counter
+		s.counter += 1
+		if s.counter == 0 {
+			panic("chacha20: counter overflow")
+		}
+
+		// pad to 64 bytes if needed
+		in, out := src[i:], dst[i:]
+		if i == fin {
+			// src[fin:] has already been copied into s.buf before
+			// the main loop
+			in, out = s.buf[len(s.buf)-64:], s.buf[len(s.buf)-64:]
+		}
+		in, out = in[:64], out[:64] // BCE hint
+
+		// XOR the key stream with the source and write out the result
+		xor(out[0:], in[0:], x0)
+		xor(out[4:], in[4:], x1)
+		xor(out[8:], in[8:], x2)
+		xor(out[12:], in[12:], x3)
+		xor(out[16:], in[16:], x4)
+		xor(out[20:], in[20:], x5)
+		xor(out[24:], in[24:], x6)
+		xor(out[28:], in[28:], x7)
+		xor(out[32:], in[32:], x8)
+		xor(out[36:], in[36:], x9)
+		xor(out[40:], in[40:], x10)
+		xor(out[44:], in[44:], x11)
+		xor(out[48:], in[48:], x12)
+		xor(out[52:], in[52:], x13)
+		xor(out[56:], in[56:], x14)
+		xor(out[60:], in[60:], x15)
+	}
+	// copy any trailing bytes out of the buffer and into dst
+	if rem != 0 {
+		s.len = 64 - rem
+		copy(dst[fin:], s.buf[len(s.buf)-64:])
+	}
+}
+
+// Advance discards bytes in the key stream until the next 64 byte block
+// boundary is reached and updates the counter accordingly. If the key
+// stream is already at a block boundary no bytes will be discarded and
+// the counter will be unchanged.
+func (s *Cipher) Advance() {
+	s.len -= s.len % 64
+	if s.len == 0 {
+		s.buf = [len(s.buf)]byte{}
+	}
+}
+
+// XORKeyStream crypts bytes from in to out using the given key and counters.
+// In and out must overlap entirely or not at all. Counter contains the raw
+// ChaCha20 counter bytes (i.e. block counter followed by nonce).
+func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
+	s := Cipher{
+		key: [8]uint32{
+			binary.LittleEndian.Uint32(key[0:4]),
+			binary.LittleEndian.Uint32(key[4:8]),
+			binary.LittleEndian.Uint32(key[8:12]),
+			binary.LittleEndian.Uint32(key[12:16]),
+			binary.LittleEndian.Uint32(key[16:20]),
+			binary.LittleEndian.Uint32(key[20:24]),
+			binary.LittleEndian.Uint32(key[24:28]),
+			binary.LittleEndian.Uint32(key[28:32]),
+		},
+		nonce: [3]uint32{
+			binary.LittleEndian.Uint32(counter[4:8]),
+			binary.LittleEndian.Uint32(counter[8:12]),
+			binary.LittleEndian.Uint32(counter[12:16]),
+		},
+		counter: binary.LittleEndian.Uint32(counter[0:4]),
+	}
+	s.XORKeyStream(out, in)
+}
diff --git a/libgo/go/golang_org/x/crypto/internal/chacha20/chacha_noasm.go b/libgo/go/golang_org/x/crypto/internal/chacha20/chacha_noasm.go
new file mode 100644
index 00000000000..91520d1de07
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/internal/chacha20/chacha_noasm.go
@@ -0,0 +1,16 @@
+// 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 !s390x gccgo appengine
+
+package chacha20
+
+const (
+	bufSize = 64
+	haveAsm = false
+)
+
+func (*Cipher) xorKeyStreamAsm(dst, src []byte) {
+	panic("not implemented")
+}
diff --git a/libgo/go/golang_org/x/crypto/internal/chacha20/chacha_s390x.go b/libgo/go/golang_org/x/crypto/internal/chacha20/chacha_s390x.go
new file mode 100644
index 00000000000..0c1c671c40b
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/internal/chacha20/chacha_s390x.go
@@ -0,0 +1,30 @@
+// 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 s390x,!gccgo,!appengine
+
+package chacha20
+
+var haveAsm = hasVectorFacility()
+
+const bufSize = 256
+
+// hasVectorFacility reports whether the machine supports the vector
+// facility (vx).
+// Implementation in asm_s390x.s.
+func hasVectorFacility() bool
+
+// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
+// be called when the vector facility is available.
+// Implementation in asm_s390x.s.
+//go:noescape
+func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32, buf *[256]byte, len *int)
+
+func (c *Cipher) xorKeyStreamAsm(dst, src []byte) {
+	xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter, &c.buf, &c.len)
+}
+
+// EXRL targets, DO NOT CALL!
+func mvcSrcToBuf()
+func mvcBufToDst()
diff --git a/libgo/go/golang_org/x/crypto/internal/chacha20/chacha_test.go b/libgo/go/golang_org/x/crypto/internal/chacha20/chacha_test.go
new file mode 100644
index 00000000000..bf993304e8e
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/internal/chacha20/chacha_test.go
@@ -0,0 +1,188 @@
+// 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 chacha20
+
+import (
+	"encoding/hex"
+	"fmt"
+	"math/rand"
+	"testing"
+)
+
+func TestCore(t *testing.T) {
+	// This is just a smoke test that checks the example from
+	// https://tools.ietf.org/html/rfc7539#section-2.3.2. The
+	// chacha20poly1305 package contains much more extensive tests of this
+	// code.
+	var key [32]byte
+	for i := range key {
+		key[i] = byte(i)
+	}
+
+	var input [16]byte
+	input[0] = 1
+	input[7] = 9
+	input[11] = 0x4a
+
+	var out [64]byte
+	XORKeyStream(out[:], out[:], &input, &key)
+	const expected = "10f1e7e4d13b5915500fdd1fa32071c4c7d1f4c733c068030422aa9ac3d46c4ed2826446079faa0914c2d705d98b02a2b5129cd1de164eb9cbd083e8a2503c4e"
+	if result := hex.EncodeToString(out[:]); result != expected {
+		t.Errorf("wanted %x but got %x", expected, result)
+	}
+}
+
+// Run the test cases with the input and output in different buffers.
+func TestNoOverlap(t *testing.T) {
+	for _, c := range testVectors {
+		s := New(c.key, c.nonce)
+		input, err := hex.DecodeString(c.input)
+		if err != nil {
+			t.Fatalf("cannot decode input %#v: %v", c.input, err)
+		}
+		output := make([]byte, c.length)
+		s.XORKeyStream(output, input)
+		got := hex.EncodeToString(output)
+		if got != c.output {
+			t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output)
+		}
+	}
+}
+
+// Run the test cases with the input and output overlapping entirely.
+func TestOverlap(t *testing.T) {
+	for _, c := range testVectors {
+		s := New(c.key, c.nonce)
+		data, err := hex.DecodeString(c.input)
+		if err != nil {
+			t.Fatalf("cannot decode input %#v: %v", c.input, err)
+		}
+		s.XORKeyStream(data, data)
+		got := hex.EncodeToString(data)
+		if got != c.output {
+			t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output)
+		}
+	}
+}
+
+// Run the test cases with various source and destination offsets.
+func TestUnaligned(t *testing.T) {
+	const max = 8 // max offset (+1) to test
+	for _, c := range testVectors {
+		input := make([]byte, c.length+max)
+		output := make([]byte, c.length+max)
+		for i := 0; i < max; i++ { // input offsets
+			for j := 0; j < max; j++ { // output offsets
+				s := New(c.key, c.nonce)
+
+				input := input[i : i+c.length]
+				output := output[j : j+c.length]
+
+				data, err := hex.DecodeString(c.input)
+				if err != nil {
+					t.Fatalf("cannot decode input %#v: %v", c.input, err)
+				}
+				copy(input, data)
+				s.XORKeyStream(output, input)
+				got := hex.EncodeToString(output)
+				if got != c.output {
+					t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output)
+				}
+			}
+		}
+	}
+}
+
+// Run the test cases by calling XORKeyStream multiple times.
+func TestStep(t *testing.T) {
+	// wide range of step sizes to try and hit edge cases
+	steps := [...]int{1, 3, 4, 7, 8, 17, 24, 30, 64, 256}
+	rnd := rand.New(rand.NewSource(123))
+	for _, c := range testVectors {
+		s := New(c.key, c.nonce)
+		input, err := hex.DecodeString(c.input)
+		if err != nil {
+			t.Fatalf("cannot decode input %#v: %v", c.input, err)
+		}
+		output := make([]byte, c.length)
+
+		// step through the buffers
+		i, step := 0, steps[rnd.Intn(len(steps))]
+		for i+step < c.length {
+			s.XORKeyStream(output[i:i+step], input[i:i+step])
+			if i+step < c.length && output[i+step] != 0 {
+				t.Errorf("length=%v, i=%v, step=%v: output overwritten", c.length, i, step)
+			}
+			i += step
+			step = steps[rnd.Intn(len(steps))]
+		}
+		// finish the encryption
+		s.XORKeyStream(output[i:], input[i:])
+
+		got := hex.EncodeToString(output)
+		if got != c.output {
+			t.Errorf("length=%v: got %#v, want %#v", c.length, got, c.output)
+		}
+	}
+}
+
+// Test that Advance() discards bytes until a block boundary is hit.
+func TestAdvance(t *testing.T) {
+	for _, c := range testVectors {
+		for i := 0; i < 63; i++ {
+			s := New(c.key, c.nonce)
+			z := New(c.key, c.nonce)
+			input, err := hex.DecodeString(c.input)
+			if err != nil {
+				t.Fatalf("cannot decode input %#v: %v", c.input, err)
+			}
+			zeros, discard := make([]byte, 64), make([]byte, 64)
+			so, zo := make([]byte, c.length), make([]byte, c.length)
+			for j := 0; j < c.length; j += 64 {
+				lim := j + i
+				if lim > c.length {
+					lim = c.length
+				}
+				s.XORKeyStream(so[j:lim], input[j:lim])
+				// calling s.Advance() multiple times should have no effect
+				for k := 0; k < i%3+1; k++ {
+					s.Advance()
+				}
+				z.XORKeyStream(zo[j:lim], input[j:lim])
+				if lim < c.length {
+					end := 64 - i
+					if c.length-lim < end {
+						end = c.length - lim
+					}
+					z.XORKeyStream(discard[:], zeros[:end])
+				}
+			}
+
+			got := hex.EncodeToString(so)
+			want := hex.EncodeToString(zo)
+			if got != want {
+				t.Errorf("length=%v: got %#v, want %#v", c.length, got, want)
+			}
+		}
+	}
+}
+
+func BenchmarkChaCha20(b *testing.B) {
+	sizes := []int{32, 63, 64, 256, 1024, 1350, 65536}
+	for _, size := range sizes {
+		s := size
+		b.Run(fmt.Sprint(s), func(b *testing.B) {
+			k := [32]byte{}
+			c := [16]byte{}
+			src := make([]byte, s)
+			dst := make([]byte, s)
+			b.SetBytes(int64(s))
+			b.ResetTimer()
+			for i := 0; i < b.N; i++ {
+				XORKeyStream(dst, src, &c, &k)
+			}
+		})
+	}
+}
diff --git a/libgo/go/golang_org/x/crypto/internal/chacha20/vectors_test.go b/libgo/go/golang_org/x/crypto/internal/chacha20/vectors_test.go
new file mode 100644
index 00000000000..b441fbd149a
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/internal/chacha20/vectors_test.go
@@ -0,0 +1,578 @@
+// 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 chacha20
+
+// Test vectors for ChaCha20 implementations.
+
+type testCase struct {
+	length int
+	nonce  [3]uint32
+	key    [8]uint32
+	input  string
+	output string
+}
+
+var testVectors = [...]testCase{
+	{
+		length: 0,
+		nonce:  [3]uint32{0x94d13317, 0x6b6a2b3, 0x3ffe0036},
+		key:    [8]uint32{0x9da8a3b6, 0x3abf4ae6, 0xa2f19cae, 0x1068c707, 0x72e4801e, 0xce165d92, 0x61e7028f, 0x82ac3d57},
+		input:  "",
+		output: "",
+	},
+	{
+		length: 5,
+		nonce:  [3]uint32{0x469fadd, 0xee3fcc1e, 0x45cf77b0},
+		key:    [8]uint32{0x3477e02b, 0x45bf809f, 0x27f4a1fa, 0xdb901de8, 0xd8a190dc, 0x1d2c21d4, 0x87bdf2ac, 0xdfbf0000},
+		input:  "23dbad0780",
+		output: "415a3e498d",
+	},
+	{
+		length: 9,
+		nonce:  [3]uint32{0x512a6b49, 0x8df9af6d, 0x5336a2a5},
+		key:    [8]uint32{0xe9124c25, 0x4fd1a373, 0x7945f7bb, 0xeed5f064, 0x29c4185d, 0x3c9acf13, 0x4c94a367, 0x7c2c2c53},
+		input:  "f518831fab69c054a6",
+		output: "cfe40f63f81391484b",
+	},
+	{
+		length: 12,
+		nonce:  [3]uint32{0xca697a9e, 0x6b2f6717, 0xb7859220},
+		key:    [8]uint32{0xfc825020, 0x5ca4410b, 0x7d5285d0, 0x160a1c9d, 0x15470b41, 0x3634742a, 0xe64aa7fa, 0xca0be67a},
+		input:  "805fad1d62951537aeed9859",
+		output: "47bd303f93c3ce04bce44710",
+	},
+	{
+		length: 14,
+		nonce:  [3]uint32{0xcded3db3, 0x35770a7f, 0x6aede9b},
+		key:    [8]uint32{0x44632def, 0xa5e420a7, 0xfc12a8f, 0x63b79a15, 0x337de314, 0xb82fbf16, 0x3104bc57, 0x677c9227},
+		input:  "f4e8a7577affb841cf48392cf5df",
+		output: "f445c0fb7e3d5bfdab47090ddee6",
+	},
+	{
+		length: 15,
+		nonce:  [3]uint32{0x348a50b1, 0x4acc9280, 0x8d6014ce},
+		key:    [8]uint32{0x34bd31a8, 0x2808f47e, 0x9d8b19f9, 0x4df59683, 0x31584348, 0x34a74a45, 0xde174a2, 0x29d4c7dc},
+		input:  "1179b71ec4dc34bd812f742b5a0b27",
+		output: "cc7f80f333c647d6e592e4f7ecc834",
+	},
+	{
+		length: 20,
+		nonce:  [3]uint32{0xc8754703, 0x9188c521, 0xac8ce8a6},
+		key:    [8]uint32{0xe93c79ed, 0xce89162b, 0x116a8366, 0xecdc657f, 0x5bc81d98, 0xff5d2f52, 0x171f3ebb, 0x50773f2f},
+		input:  "7bd94943d55392d0311c413ac755ce0347872ba3",
+		output: "c43665de15136af232675d9d5dbbeca77f3c542a",
+	},
+	{
+		length: 21,
+		nonce:  [3]uint32{0x9a8655cb, 0x6e9d6ea5, 0x5dad705e},
+		key:    [8]uint32{0x3542d5b3, 0x1f7bfd8f, 0x1038abf8, 0x7214e8ec, 0xedd05693, 0x60e663bd, 0xe8e5d506, 0xeea923a2},
+		input:  "1505f669acc5ad9aaa0e993ba8c24e744d13655e1f",
+		output: "26cad1ccf4cf4c49b267ab7be10bc2ffa3ba66bc86",
+	},
+	{
+		length: 25,
+		nonce:  [3]uint32{0x3f202ca4, 0x63fc86, 0x7260a10e},
+		key:    [8]uint32{0xe28ab1d6, 0xe83b3d47, 0x671271ca, 0xb977bcff, 0xa2f64476, 0x311d79b4, 0x180d91d0, 0xec1a6e0c},
+		input:  "20070523ddb4ebf0d5f20fd95aacf47fb269ebadda6879638a",
+		output: "5ce972624cb2b7e7c28f5b865ba08c887911b4f5e361830a4b",
+	},
+	{
+		length: 31,
+		nonce:  [3]uint32{0xcf8671ea, 0x8d72df2f, 0x8b5a538a},
+		key:    [8]uint32{0xe46ca2bb, 0xd06ab5ef, 0xb0e2966b, 0x54dd0c2d, 0x8815d89a, 0x426c30a9, 0x15b0f1e, 0x254bae75},
+		input:  "d10f8050c1186f92e26f351db36490d82ea677498562d8d4f487a0a4058adf",
+		output: "f30c11bc553b2baf6870760d735680897c9fee168f976b2a33ef395fdbd4fc",
+	},
+	{
+		length: 34,
+		nonce:  [3]uint32{0xd1be983a, 0xf5aa389, 0xfa26c7e1},
+		key:    [8]uint32{0x795c6da7, 0x8cb1aadc, 0xa042359a, 0x95ea2e27, 0x128253c4, 0xaabc592f, 0x391e810, 0xf641d971},
+		input:  "e88dc380b7d45a4a762c34f310199587867516fac4a2634022b96a9f862e17714d17",
+		output: "aac98ba3821399e55a5eab5862f7f1bfc63637d700125878c2b17151f306c9aec80e",
+	},
+	{
+		length: 34,
+		nonce:  [3]uint32{0x98f5f4b8, 0x3f181d73, 0x5bf4572e},
+		key:    [8]uint32{0xa86f8cf7, 0x8db41a2b, 0xe0e03156, 0x3dad8a59, 0xb3e4d1ba, 0x75f6fb38, 0xdb94709d, 0xc3db34f3},
+		input:  "b0fcf0a731e2902787309697db2384e1cda07b60002c95355a4e261fb601f034b2b3",
+		output: "b6c8c40ddda029a70a21c25f724cc90c43f6edc407055683572a9f5e9690a1d571bb",
+	},
+	{
+		length: 40,
+		nonce:  [3]uint32{0x7289ae18, 0x7ebe7e50, 0x7d819176},
+		key:    [8]uint32{0x336c07a0, 0x4a2ea22b, 0xa8872f46, 0xa47b5e28, 0xbe645e3f, 0x371c6591, 0xd2dc237a, 0x92c59580},
+		input:  "cf9ec6fa3f0a67488adb5598a48ed916729a1e416d206f9675dfa9fd6585793f274f363bbca348b3",
+		output: "bb7ed8a199aa329dcd18736ce705804ffae8c3e2ba341ae907f94f4672d57175df25d28e16962fd6",
+	},
+	{
+		length: 47,
+		nonce:  [3]uint32{0xfd3181de, 0x8b193e26, 0xbebc799},
+		key:    [8]uint32{0x781a4c2e, 0x27ab55e2, 0x814aaf43, 0xa0bab01, 0x9de62ce0, 0x472b03d2, 0xdfee18e8, 0x8b855b93},
+		input:  "be9a8211d68642310724eda3dd02f63fcc03a101d9564b0ecee6f4ecececcb0099bb26aabee46b1a2c0416b4ac269e",
+		output: "3152f317cf3626e26d02cff9392619ea02e22115b6d43d6dd2e1177c6bb3cb71c4a90c3d13b63c43e03605ec98d9a1",
+	},
+	{
+		length: 51,
+		nonce:  [3]uint32{0x27b02ff6, 0xa510613e, 0x218b22d8},
+		key:    [8]uint32{0x62fc7732, 0xcef06cf4, 0xa4f45ed5, 0x2f96654f, 0x9f2b956e, 0x42b572f4, 0x5bb59c86, 0x35e4784f},
+		input:  "495343a257250f8970f791f493b89d10edba89806b88aaaeb3b5aefd078ba7b765746164bce653f5e6c096dd8499fb76d97d77",
+		output: "62c01f426581551b5b16e8b1a3a23c86bcdd189ab695dbea4bf811a14741e6ebbb0261ef8ae47778a6be7e0ef11697b891412c",
+	},
+	{
+		length: 52,
+		nonce:  [3]uint32{0x9db97a63, 0xff50248, 0xf2b6df56},
+		key:    [8]uint32{0x2b657a8f, 0xfe67575d, 0xaa56d261, 0x30179a97, 0xaefcfff1, 0x9b8eb698, 0x1efe3756, 0xb4ea450c},
+		input:  "e37fbbd3fe37ce5a99d18e5dcb0dafe7adf8b596528708f7d310569ab44c251377f7363a390c653965e0cb8dd217464b3d8f79c1",
+		output: "b07d4c56fb83a49e8d9fc992e1230bb5086fecbd828cdbc7353f61b1a3cec0baf9c5bf67c9da06b49469a999ba3b37916ec125be",
+	},
+	{
+		length: 56,
+		nonce:  [3]uint32{0xc1dfec38, 0x7d7503d3, 0x9a3e3c66},
+		key:    [8]uint32{0x8614d8e7, 0xde9b0413, 0x2a48b4fa, 0xcbbde744, 0xad5ddc5e, 0x9144d83e, 0x74d9d617, 0x230bdb45},
+		input:  "9efab614388a7d99102bcc901e3623d31fd9dd9d3c3338d086f69c13e7aa8653f9ce76e722e5a6a8cbbbee067a6cb9c59aa9b4b4c518bbed",
+		output: "829d9fe74b7a4b3aeb04580b41d38a156ffbebba5d49ad55d1b0370f25abcd41221304941ad8e0d5095e15fbd839295bf1e7a509a807c005",
+	},
+	{
+		length: 63,
+		nonce:  [3]uint32{0xc7e2521c, 0x795499b4, 0xc7946cd7},
+		key:    [8]uint32{0x53fce774, 0x9a4b53bf, 0x5f614134, 0xa3c39414, 0xa8a07c72, 0x93242311, 0x43aeec99, 0x216deb5a},
+		input:  "03b5d7ab4bd8c9a4f47ec122cbeb595bd1a0d58de3bb3dcc66c4e288f29622d6863e846fdfb27a90740feb03a4761c6017250bc0f129cc65d19680ab9d6970",
+		output: "83db55d9eb441a909268311da67d432c732ad6bda0a0dae710d1bce040b91269deb558a68ced4aa5760ca0b9c5efc84e725f297bdbdadbc368bea4e20261c5",
+	},
+	{
+		length: 66,
+		nonce:  [3]uint32{0x1d41f0a1, 0x7c3b7778, 0x6991eea5},
+		key:    [8]uint32{0x1f213e39, 0x56261d14, 0x15fc7c2c, 0x21feccc5, 0xa95684c5, 0x26600506, 0xdadcc06b, 0xf2c810b0},
+		input:  "2f4da518578a2a82c8c855155645838ca431cdf35d9f8562f256746150580ca1c74f79b3e9ae78224573da8b47a4b3cc63fbed8d4e831a6b4d796c124d87c78a66e5",
+		output: "6fc086ded3d1d5566577ccd9971e713c1126ec52d3894f09ab701116c7b5abda959cbb207f4468eb7b6a6b7e1b6d2bc6047f337499d63522f256ee751b91f84f70b6",
+	},
+	{
+		length: 72,
+		nonce:  [3]uint32{0x749f022c, 0xa021dab0, 0x648c2252},
+		key:    [8]uint32{0xa1ace7b0, 0x567a0ea1, 0x52af13b9, 0xcba30c08, 0xe07a6d74, 0x5c3bca39, 0x85b2ac07, 0x3b5afc0},
+		input:  "55739a1738b4a4028021b21549e2661b050e3d830ad9a56f57bfcaca3e0f72051b9ca92411840061083e5e45124d8425061ab26c632ac7852118411ac80026da946357c630f27225",
+		output: "8051bf98f8f2617e159ba205a9342ab700973dd045e09321805eed89e419f37f3211c5aa82666b9a097270babc26d3bfe0c990fe245ae982a31f23cfbf6156b5c8cfb77f340e2bf5",
+	},
+	{
+		length: 74,
+		nonce:  [3]uint32{0x23c16ba8, 0x9fd1cd4e, 0xcb224ecb},
+		key:    [8]uint32{0xb694404a, 0x86b5f198, 0x10fd1bff, 0x13a84e54, 0xab21e509, 0x7443d764, 0x931b3f1, 0x686e87f2},
+		input:  "7ffd8d5970fdee613eeae531d1c673fd379d64b0b6bfedd010433b080b561038f7f266fa7e15d7d8e10d23f21b9d7724bb200b0f58b9250483e784f4a6555d09c234e8d1c549ebb76a8e",
+		output: "c173617e36ea20ce04c490803b2098bd4f1ff4b31fdca1c51c6475ade83892c5f12731652d5774631d55ae2938617a5e9462bb6083328a23a4fba52de50ca9075586f2efc22aae56e3a8",
+	},
+	{
+		length: 81,
+		nonce:  [3]uint32{0xd65f6f29, 0xf3f76219, 0x9a033c9e},
+		key:    [8]uint32{0xeba017c4, 0x69e0421a, 0x449e2317, 0x29858a11, 0xd0c8523a, 0xa8b0c9a2, 0xab2ca84, 0xaf011a45},
+		input:  "7a5766097562361cfaeac5b8a6175e1ceeeda30aec5e354df4302e7700ea48c505da9fdc57874da879480ecfea9c6c8904f330cbac5e27f296b33b667fea483348f031bef761d0b8e318a8132caa7a5943",
+		output: "5e9fbf427c4f0fcf44db3180ea47d923f52bee933a985543622eff70e2b3f5c673be8e05cd7acbcadd8593da454c60d5f19131e61730a73b9c0f87e3921ee5a591a086446b2a0fadd8a4bc7b49a8e83764",
+	},
+	{
+		length: 88,
+		nonce:  [3]uint32{0xc70ee56e, 0xe58ec41, 0xafd96f61},
+		key:    [8]uint32{0x172af2bb, 0x9085d27c, 0x8ca2c44d, 0x8aa148da, 0x290c88b0, 0x88187439, 0x18d54781, 0x633f2cce},
+		input:  "0777c02a2900052d9b79f38387d2c234108a2ad066cbf7df6ea6acc5a3f86b3d6156abb5b18ad4ecf79e171383a1897e64a95ecdbba6aa3f1c7c12fe31283629ff547cb113a826cb348a7c10507cc645fa2eb97b5f22e44d",
+		output: "368c90db3464ba488340b1960e9f75d2c3b5b392bdd5622ff70e85e6d00b1e6a996ba3978ce64f8f2b5a9a90576c8f32b908233e15d2f443cccc98af87745c93c8056603407a3fb37ce0c1f8ab6384cc37c69c98bfecf337",
+	},
+	{
+		length: 92,
+		nonce:  [3]uint32{0x3006da79, 0x2748051d, 0x72c17cdc},
+		key:    [8]uint32{0x60cdb7e8, 0xcecbe928, 0xe19b7ab9, 0x30d61537, 0xa0fbc199, 0x897738bf, 0xdd7705a9, 0x3e5c1763},
+		input:  "cf2dccbcfd781c030376f9019d841ca701cb54a1791f50f50bee0c2bf178182603a4712b5916eebd5001595c3f48283f1ba097ce2e7bf94f2b7fa957ce776e14a7a570093be2de386ececbd6525e72c5970c3e7d35974b8f0b831fbc",
+		output: "7c92b8c75e6eb8675229660cedcb10334965a7737cde7336512d9eff846c670d1fa8f8a427ea4f43e66be609466711fd241ccff7d3f049bda3a2394e5aa2108abc80e859611dbd3c7ba2d044a3ececa4980dd65e823dd110fea7a548",
+	},
+	{
+		length: 96,
+		nonce:  [3]uint32{0xfc0fb1ee, 0x414cc60a, 0x4144bd67},
+		key:    [8]uint32{0x103291c6, 0x822b03b6, 0xd29ab548, 0xc88f3efe, 0x6936056a, 0x28aaa61f, 0xa0df7858, 0xdaa23519},
+		input:  "e08a8949a1bfd6a8c1186b431b6ad59b106ae5552821db69b66dc03fbc4a2b970dcf9c7da4f5082572bc978f8ee27c554c8884b5a450b36d70453348cd6cac9b80c9900cf98a4088803f564bb1281d24507b2f61ba737c8145c71b50eb0f6dfc",
+		output: "73d043acf9dcd758c7299bd1fd1f4100d61ff77d339e279bfbe6f9233b0d9afa24992a9c1c7a19545d469fdfb369c201322f6fe8c633fcdcffef31032bfb41b9fb55506e301d049fd447d61f974a713debeaed886f486a98efd3d6c3f25fbb30",
+	},
+	{
+		length: 103,
+		nonce:  [3]uint32{0xc2030c57, 0x1e3b59e1, 0x607ede1a},
+		key:    [8]uint32{0xd1bac2b5, 0x56a94583, 0x628b479b, 0x3056a51e, 0x69bf8f8f, 0x2df1e03d, 0x4b9d48d2, 0x7df5c379},
+		input:  "a0c302120111f00c99cff7d839cdf43207a7e2f73d5dd888daa00d84254db0e621a72493480420c9c61ce1cfc54188ff525bb7a0e6c1cd298f598973a1de9fd2d79a21401588775b0adbe261ba4e4f79a894d1bd5835b5924d09ba32ef03cb4bc0bd6eb4ee4274",
+		output: "bc714bd7d8399beedc238f7ddeb0b99d94ad6bf8bf54548a3e4b90a76aa5673c91db6482591e8ff9126e1412bce56d52a4c2d89f22c29858e24482f177abacef428d0ae1779f0ae0778c44f9f02fe474da93c35c615b5fad29eca697978891f426714441317f2b",
+	},
+	{
+		length: 109,
+		nonce:  [3]uint32{0xf44dc81f, 0xcf6e03e7, 0xf4966796},
+		key:    [8]uint32{0xd7b12f4, 0x683f4789, 0xc7828fb4, 0x820fc6a0, 0xc51231eb, 0xe46716d7, 0x4036ef93, 0x26afb96c},
+		input:  "ebce290c03c7cb65d053918ba2da0256dc700b337b8c124c43d5da4746888ca78387feea1a3a72c5e249d3d93a1907977dd4009699a15be5da2ca89c60e971c8df5d4553b61b710d92d3453dea595a0e45ae1e093f02ea70608b7b32f9c6aadc661a052f9b14c03ea0117a3192",
+		output: "cbb8c4ec827a1123c1141327c594d4a8b0b4a74b0008115bb9ec4275db3a8e5529a4f145551af29c473764cbaa0794b2d1eb1066f32a07fd39f5f3fe51498c46fba5310ae7c3664571d6a851e673ded3badc25e426f9c6038724779aa6d2d8ec3f54865f7df612e25575635ab5",
+	},
+	{
+		length: 115,
+		nonce:  [3]uint32{0x8d3e461b, 0x7e05c360, 0x3bbbafdd},
+		key:    [8]uint32{0xf9b917c9, 0x9af89bf7, 0x7decbbc9, 0xe7e5ea7b, 0x9b4aab55, 0x90eff6be, 0xa19b6d90, 0xb9f69b1a},
+		input:  "275c97de985aa265332065ccce437770b110737a77dea62137a5d6cb62e9cb8b504d34334a58a71aba153d9b86f21377467b2fafaf54829331bf2ce0009acb37842b7a4b5f152aab650a393153f1ed479abc21f7a6fe205b9852ff2f7f3a0e3bfe76ca9770efada4e29e06db0569a99d08648e",
+		output: "b225aa01d5c438d572deaea51ac12c0c694e0f9dc0ed2884a98e5e2943d52bb4692d7d8f12486de12d0559087e8c09e4f2d5b74e350838aa2bd36023032ccbcae56be75c6a17c59583d81a1fd60e305af5053ac89f753c9347f3040e48405232dc8428c49dcb3d9b899145f5b3bc955f34dbbe",
+	},
+	{
+		length: 119,
+		nonce:  [3]uint32{0x871f33f5, 0xe4fee3ba, 0xcb8c1e93},
+		key:    [8]uint32{0x33124903, 0x7e0287e5, 0xe9d6988f, 0x1962405f, 0x5f21c1b5, 0x2ac695e6, 0x46b200c9, 0x9fda98ba},
+		input:  "ceda15cfffd53ccebe31b5886facd863f6166e02ec65f46f54148860a5c2702e34fd204d881af6055952690cd1ffa8ba4d0e297cc165d981b371932adb935398c987baff335108c5e77f2e5dd5e1ca9a017bc376cbdbe3c0f45e079c212e8986b438444e79cd37927c1479f45c9e75b0076cc9f8679011",
+		output: "a3f1c3f885583b999c85cd118e2ababfa5a2de0c8eb28aacc161b1efee89d8de36ddeb584174c0e92011b8d667cb64009049976082072e6262933dbf7b14839805e1face375b7cbb54f9828ba1ed8aa55634ec5d72b6351feff4d77a3a22b34203b02e096f5e5f9ae9ad6a9dd16c57ce6d94dcc8873d18",
+	},
+	{
+		length: 120,
+		nonce:  [3]uint32{0xef553ce8, 0xdfe120ea, 0x9a047e3a},
+		key:    [8]uint32{0xbef479c1, 0x59554f8b, 0xbf97f089, 0x52316f1e, 0x141e428, 0xff26dc04, 0xe10c8f57, 0xa7568a59},
+		input:  "799bb2d634406753416b3a2b67513293a0b3496ef5b2d019758dedaaac2edd72502fc4a375b3f0d4237bc16b0e3d47e7ddc315c6aef3a23fcae2eb3a6083bc7ac4fd1b5bf0025cc1cb266b40234b77db762c747d3a7b27956cf3a4cf72320fb60c0d0713fa60b37a6cb5b21a599e79d0f06a5b7201aeb5d2",
+		output: "e84dfb3dbaac364085497aeabd197db852d3140c0c07f5f10e5c144c1fe26a50a9877649e88c6fe04283f4b7590a8d0d042ef577693f76f706e31c4979437590fe0ab03d89afb089d1be50ae173ea5458810372838eceac53bf4bac792735d8149e548efb432e236da92bf3168bbcf36f644c23efb478a4e",
+	},
+	{
+		length: 123,
+		nonce:  [3]uint32{0xd98124a0, 0x78cd80aa, 0x3dc55cfc},
+		key:    [8]uint32{0x2286e41, 0xf13e38e3, 0xf735476b, 0x33c44bfc, 0xd7978797, 0x4a9c4595, 0x6080413, 0x1299fdd8},
+		input:  "b2d060bd173955f44ee01b8bfcf0a6fad017c3517e4e8c8da728379f6d54471c955615e2b1effe4ce3d0139df225223c361be1cac416ade10a749c5da324563696dae8272577e44e8588cd5306bff0bfbdb32af3ac7cbc78be24b51baf4d5e47cf8f1d6b0a63ed9359da45c3e7297b2314028848f5816feab885e2",
+		output: "ffa4aa66dd5d39694ae64696bfa96f771accef68f195456ad815751e25c47ed4f27b436f1b3e3fcaa3e0d04133b53559c100cd633ced3d4321fc56225c85d2443727bce40434455aa4c1f3e6768c0fe58ad88b3a928313d41a7629f1ce874d2c8bcf822ebdaebfd9d95a31bb62daab5385eb8eefe026e8cbf1ff7a",
+	},
+	{
+		length: 127,
+		nonce:  [3]uint32{0x53106b0f, 0xdf11fd81, 0x69d1b6f3},
+		key:    [8]uint32{0x736b138, 0x55cde194, 0xf8273c1, 0xf7c268e6, 0x61362bd5, 0xbb3cb455, 0x44d3c9fc, 0x7d56d3fd},
+		input:  "4f0171d7309493a349530940feece3c6200693f9cff38924114d53f723d090fffa3c80731b5ca989d3e924d1fa14266632cb9ab879e1a36df22dc9f8d1dadea229db72fded0c42187c38b9fa263c20e5fb5b4aa80eb90e8616e36d9b8c613b371c402343823184ecad3532058a46cf9e7ea5a9ecad043ac3028cbcc3f36d32",
+		output: "88c773ff34b23e691e14018ba1b2bd48a4a6979b377eb0d68336ce6192dcd5177e6b4f1c4bea2df90af56b35fe2a1d6279d253c0194dcbca9bf136f92d69165b216e4c9d1ce6b3fbe40c71e32c3f4088de352732d0e2bad9c16fd0bb9bde3d6c30257ce063432d09f19da79d49aa7641124a6c9e3f09449e911edbae11a053",
+	},
+	{
+		length: 130,
+		nonce:  [3]uint32{0x5e90ffbd, 0xa898f173, 0x269f9a88},
+		key:    [8]uint32{0x5244e05f, 0xf9adbe9b, 0x9e9f54ac, 0x23460046, 0x6782cdea, 0xba982c96, 0xc721506b, 0xed10f7e3},
+		input:  "8f8d9e18d3212bd20b96d75c06d1a63622fd83d13f79d542e45996135368772ea81511302a0d87e246dd346314cfe019bae8a5c97f567f12d82aca98dfea397c6a47dd0c419f1c609d9c52dcfcbe7eee68b2635954206ed592b7081442ce9ce3187d10ccd41cc856fb924b011f817c676c9419f52a2938c7af5f76755a75eb065411",
+		output: "4e130c5df384b9c3c84aa38a744260735e93783da0337ade99f777e692c5ea276ac4cc65880b4ae9c3b96888760fdddb74bc2e2694bedf1ee6f14619c8015f951ba81b274b466e318d09defe80bdbed57bc213ac4631d2eb14c8e348181d60f6295ceee1e9231ae047830ef4778ff66146621b76974773b5d11c8e17a476450f46ef",
+	},
+	{
+		length: 130,
+		nonce:  [3]uint32{0x308e39e8, 0x9aa4f14f, 0xf511db96},
+		key:    [8]uint32{0x833b5219, 0x4b82e588, 0x4b2d652c, 0x7c8f6ed7, 0xfe4be863, 0x9d3a50e5, 0xb888099b, 0x9f8d1968},
+		input:  "30d2379dd3ceae612182576f9acf6de505ab5a9445fe1a86ae75c5c29429e11c50fd9ec657b29b173a3763b1e171b5a7da1803ba5d64fccb2d32cb7788be194dbca00c3c91774c4c4c8ede48c1027d7cc8b387101a4fe5e44a1d9693b2f627626025072806083aadbced91c9711a0171f52ffb8ed5596cf34130022398c8a1da99c7",
+		output: "b1e8da34ad0189038ee24673979b405ef73fdbdd6f376f800031d64005a4ebed51a37f2180571223848decbea6dd22b198ab9560d7edc047c5d69183dc69b5fca346911d25cb2a1a9f830dc6382ad0024e8c3eef3aa2d155abcfe43bff01956a5e20a862fbed5c5e8df8eed0601a120caac634b068314e221f175baa11ae29002bb9",
+	},
+	{
+		length: 135,
+		nonce:  [3]uint32{0xa5feca5a, 0x753ac1b4, 0xc5a46609},
+		key:    [8]uint32{0xabbf4859, 0x828d9bf6, 0xf7f7aa6d, 0x25208ca2, 0xd7a4c0ad, 0x2fdd3282, 0x2bfcb8c2, 0x8389d84b},
+		input:  "d9404ccdcc8ef128a1b1ace4f9f1669d274ec82aa914cac34b83ac00b236478fd6167e96ec658850c6c139eb0f6fc0dd7191ba9a39828032008f7f37eb9a8df9d6cdd54240e600efe7fc49a674000c5030d825b2c5c96d0f19b8ecdbf4eeb86d3e569c5e3131abc7d6359dd4255284ccacf150d42e7a899536d51ee6db329654a4581c5ac6e419",
+		output: "c5534b5fb40b4834300e9577a9d87440c5272263d06e6aee84aa92cdf5d1b033145d336f26e5fe55c09a7e75753af93d0786dfc1cb435e86c67bd3ec8e766d0801b99e68691e2c3c3ffec539cf62e68285ea9027daa2716cd6f97e8eb7b9e266357a25eb2d4839a829508a6b7228f2832b3cd998f77597ae530430e6e4ecb53eb9efe456863a04",
+	},
+	{
+		length: 135,
+		nonce:  [3]uint32{0x12aa5846, 0x88604f6c, 0xc10d9585},
+		key:    [8]uint32{0x1491ccd6, 0x602f559d, 0xd4080c06, 0x202fabd, 0xffd3f4f8, 0xbf144c17, 0x88bf3f3c, 0x8083375},
+		input:  "231765f832927461f338aceb0f4cf51fd8469348c69c549c1dec7333d4aa4968c1ed58b65ab3fe3d0562600a2b076d56fd9ef91f589752e0455dd1d2e614cacfc0d757a11a4a2264bd38f23d3cca108632201b4f6c3b06477467726dde0c2f3aee01d66d788247663f1d0e66b044da9393ede27b9905b44115b067914961bdade85a2eca2844e1",
+		output: "1dd35f3f774f66d88cb7c2b23820ee078a093d0d85f86c4f103d869f93e2dbdd8a7cb8f101084fe1d7281a71754ec9aac5eb4fca8c365b24ed80e695caace1a8781a5a225938b50b8be96d0499752fdabd4f50d0b6ce396c6e2ca45308d1f2cc5a2a2361a8ca7a334e6ee62d466d74a1b0bf5b352f4ef6d8f8c589b733748bd3d7cda593243fab",
+	},
+	{
+		length: 140,
+		nonce:  [3]uint32{0x1c9d70f0, 0xa088a367, 0x4ec24d2b},
+		key:    [8]uint32{0x494e9775, 0xd07a852, 0xaf8af24a, 0xc65b825c, 0xc5e06780, 0x17fbbace, 0x651d71b5, 0xf548d8ef},
+		input:  "e46841f12d98aeb7710b9162d342895a971b0e3a499886bbb6aa74dc744a28d89a54542b628acdc2f693cb7c03f73fc3b74069bc3f2d000a145fb8a806cdc7d6fa971da09a33b92851cc3d1f6f5646d7fa2b1d564876feefeb63b6e66dba1c0b86ca345235bb822e0f93132346840d2a3d6eb1b541178ea51affc7b31f8da02732cc4e5bcb5d8683ae0a91c9",
+		output: "1dcbfd0bb2b905656c52bd7b1bcdad9b4d434ae9ac221a0d3a316115cdd4a463fa9b3444d2612a4e277d0dcd881fa6e80e59e5a54e35e1a14747aed31edf4ac24214f9d9c329ebe2157620b64efaded9976549bc4aa100d5c15be3f85f700f8a21dfe77590dfee2de9a23cc1ed1e44f32ebf68ca289b097bc13b42802dc7c75309c4afc25b5741839f7db3d5",
+	},
+	{
+		length: 144,
+		nonce:  [3]uint32{0x23067b8b, 0x5b276c6d, 0xaeca6c60},
+		key:    [8]uint32{0x29d64488, 0x893a2973, 0x32e3b4ef, 0x2af3d5d4, 0x95ec01b, 0xc805b64c, 0x884e8b7d, 0x798d7062},
+		input:  "e98e4a9550bdd29e4106f0cc8669dcc646a69438408e9a72c7cdb9b9d437b5f7a13fcb197629541c55bca1f8972a80cd1c1f591a0e24f977cdeb84763eab2648e42286e6473ea95e3a6a43b07a32b6a6cd80fe007ba0cf7f5ac7e651431f5e72690ec52a7134f9757daf0d8eff6b831a229db4ab8288f6bbf81e16fedebe621fd1737c8792cfd15fb3040f4f6a4cbc1e",
+		output: "5c69cf522c058790a3bc38979e172b60e71f7896d362d754edc1668d4f388b3fc0acdf40786d2f34886e107a142b1e724b9b9b171cb0e38fd78b35f8ac5269d74296c39c9f8628d848f57af9d8525a33f19021db2b9c64ba113171ebb3882075019ec7e77b51ce80b063ed41d48dad481d9536c030002a75d15c1c10ce0ec3ff17bc483f8416055a99b53035f4b6ea60",
+	},
+	{
+		length: 148,
+		nonce:  [3]uint32{0x2b079658, 0xbdf5da85, 0x8a75450d},
+		key:    [8]uint32{0x49c9eaa3, 0x62048819, 0x9baacfa5, 0x3870addc, 0x5c682e1, 0xf4f9fff3, 0xa3848e4b, 0xac1ebc1},
+		input:  "ce0f0d900dd0d31749d08631ec59f216a1391f66a73bae81d3b0e2919a461bc9a14d6a01b827e3bcb55bbccf27c1ed574157e6becd5cf47181a73c9d3e865ab48a20551027e560e965876b0e1a256bfa5cb5179bf54bd8ec65e5570e374b853b37bf4b3ef1ec612d288ebc19275fa88da9419e012f957f9b6a7e375b3377db0eb3619c731aebfeb0930772b4020d3a3e90723e72",
+		output: "b06981b57fe184091ef9f8ccf522a5bcdb59bf9a68a3ddb817fdd999a6ecf81053a602141cf1b17017bae592b6b6e64756631a2b29a9e1b4f877c8b2ae30f71bc921e4f34b6f9cd8e587c57a30245f80e95005d0f18f5114400785140e6743da352d921fb4a74632a9c40115ad7706263ac9b41a11609fa0c42fc00f8d60931976162598df63ebad9496dd8943d25a03fa47475c",
+	},
+	{
+		length: 148,
+		nonce:  [3]uint32{0x98e8ab8, 0x84d8e77b, 0xbb305841},
+		key:    [8]uint32{0x46b5f93c, 0xc8b2778d, 0x2cc5278f, 0xd2a3904c, 0x6ce5d4f, 0xc4459e8, 0x4a35c30, 0x2feadc02},
+		input:  "eccfd66bdc691478f354b8423d6a3f20932a1f591d8e6cefa734975fb8ee6881b6dc92c0d1d5ed54fd1999efd7f11ac697a1f130587dd895eb498c9a8fc7d1714c385ec156ecae3bdea2a3462834245e724531d0fedda2b77693a53ed7354b758e875b23cfc83219a091fb2076e7a88cd77f779ed96f8d81ffa3fe5059303ac706086494b9f2982f4f88a0c6fadc3748625004db",
+		output: "925529047d4177b72bf50905ba77e47608815522c1829b24046e439d5451901257903a5409fb910373167e8b7f4fdfa543a477608ddfc11bbd1efc138366961463b9915b302a346b795dd593f6fcf4fa73529b6fe83079552aabbe99474a72806f59688d826675fa7f6649b9f5307e5028853c9821b8c4a1a0fc4bfdc7c8c78b25aeaba2b5821d17b36317381a3bd578917d2504",
+	},
+	{
+		length: 152,
+		nonce:  [3]uint32{0x2e2a6e4a, 0x9a6d488a, 0xf9966cb6},
+		key:    [8]uint32{0x58903bff, 0xc2be173f, 0xe26128b5, 0xb6b6af53, 0x92f8eeb, 0x38cf3336, 0x7fdf90fb, 0x7ae24b37},
+		input:  "f0c7139c69413869bca980d7f192b2bc3f57e34ca4f26164e1a54a234e84e1aa285cc02cfbaef3dfba2dbb52a555ec1f6ef0e89d0b2f0bd1846e65b74444b5f003a7308965e67bed558689be2668ca10ca368fac072e0e4535a031af23b3c37c561e185872b86c9bceddb5c1199e43fb5f735384766d33710460b541b52d3f5b6c108c08e76724bcac7ad2d866a8bbeeea92a3d867660d2e",
+		output: "d2c16c7a242b493038203daec65960de384c030eb698ef6a53c36eabb7556cbfa4770eaa8bc0a2b385ad97495eeb1c03ff4e6efcb804aefa81c177dc62700a9eefe6e8dd10cff5d43a2f47463cab5eb1ee260c3826cac9bfa070f1e0435541a89ebd224d13cc43f8fff12f38091c2b3f2102d5c20d8b1c3ae4f129364bbe9f9ce2147dcf0639668ddb90dffe6a50f939f53fa7ba358e913f",
+	},
+	{
+		length: 155,
+		nonce:  [3]uint32{0x243e0198, 0x884448c, 0x9a31e760},
+		key:    [8]uint32{0x37e017bc, 0x9b1e2e90, 0x15679daa, 0xf94a23ee, 0xda86dfe, 0xc3eea84c, 0xdd199799, 0x6eeffb92},
+		input:  "7024974ebf3f66e25631c0699bcc057be0af06bc60d81a7131acaa620a998e15f385c4eaf51ff1e0a81ae5c6a7442d28a3cdc8aeb9701055e75d39ecac35f1e0ac9f9affb6f9197c0066bf39338a2286316e9d1bb7464398e411da1507c470d64f88d11d86d09e6958fa856583ace697f4ee4edc82618662cb3c5380cb4ce7f01c770aab3467d6367c409a83e447c36768a92fc78f9cbe5698c11e",
+		output: "ff56a3a6e3867588c753260b320c301ce80de8c406545fdd69025abc21ce7430cba6b4f4a08ad3d95dc09be50e67beeff20d1983a98b9cb544b91165f9a0a5b803a66c4e21bd3a10b463b7c1f565e66064f7019362290c77238d72b0ea1e264c0939d76799843439b9f09e220982eb1dc075d449412f838709428a6b8975db25163c58f40bf320514abf7a685150d37a98bac8b34ccb5245edb551",
+	},
+	{
+		length: 160,
+		nonce:  [3]uint32{0xd24e866d, 0xc59d25d8, 0xfcf623f1},
+		key:    [8]uint32{0x5f32cca0, 0x4167cac5, 0xc04943ee, 0x507fa1ec, 0xad8fdfc0, 0x6266fa2d, 0x22f05341, 0x8074143e},
+		input:  "8d79329cf647e966fde65a57fc959223c745801c55312046b791671773cca0af4cd48ead1f316eba0da44aa5d18025eced0c9ed97abaabb24570d89b5b00c179dca15dbae89c0b12bb9e67028e3ae4d6065041b76e508706bec36517a135554d8e6ef7cf3b613cbf894bec65d4dc4e8cb5ca8734ad397238e1e5f528fa11181a57dc71cc3d8c29f3aba45f746b1e8c7faace119c9ba23a05fffd9022c6c85260",
+		output: "60aea840869f7be6fcc5584b87f43d7ba91ed2d246a8f0a58e82c5153772a9561bdf08e31a0a974f8a057b04a238feb014403cd5ffe9cf231db292199198271f9793c9202387f0835a1e1dc24f85dd86cb34608923783fd38226244a2dd745071b27d49cbffebea80d9dacad1578c09852406aa15250de58d6d09cf50c3fcfff3313fac92c8dad5cb0a61ccc02c91cecee3f628e30c666698edecf81831e55ec",
+	},
+	{
+		length: 167,
+		nonce:  [3]uint32{0x30b61047, 0x810cf901, 0x4d681524},
+		key:    [8]uint32{0xe51476d0, 0xdf98008d, 0x59dfe69e, 0xdb39166, 0x6c1e4a4a, 0xfb76165e, 0x5180f185, 0x7359fb35},
+		input:  "85484293a843d2d80b72924b7972dfa97cbe5b8c6bcc096f4d5b38956eb3f13f47b02b0f759ea37014ecdecfb55f2707ef6d7e81fd4973c92b0043eac160aaf90a4f32b83067b708a08b48db7c5900d87e4f2f62b932cf0981de72b4feea50a5eb00e39429c374698cbe5b86cf3e1fc313a6156a1559f73c5bac146ceaaaf3ccf81917c3fdd0b639d57cf19ab5bc98295fff3c779242f8be486ba348bd757ba920ca6579be2156",
+		output: "bb1650260ef2e86d96d39170f355411b6561082dcc763df0e018fdea8f10e9dc48489fb7a075f7f84260aecc10abcfadbc6e1cd26924b25dedb1cc887ada49bb4e3e02006bdd39098ef404c1c320fb3b294ded3e82b3920c8798727badfb0d63853138c29cf1ebf1759423a1457b3d2c252acf0d1cde8165f01c0b2266297e688ff03756d1b06cb79a2cc3ba649d161b8d9ef1f8fb792bd823c4eabb7fb799393f4106ab324d98",
+	},
+	{
+		length: 172,
+		nonce:  [3]uint32{0x42020cbe, 0xad62af90, 0x29e53cd},
+		key:    [8]uint32{0xabad2095, 0x601ec477, 0x3bc923a1, 0x1edede1a, 0x33612355, 0x285b4858, 0xd3fd6714, 0xe0f4bcc3},
+		input:  "a2fc6e1b5281a4e0330eecd1ab4c41670570423173255979953142b78733b2910fa5540e8294208df6ae4f18672d5ac65acf851bcd394e1932db13c81b21e6f165e5538aff862e46126c650bbe055e54b31c78f2f0221d2631d66ef6d3f4c5ae25eada043b74d8770e2c29799c0954d8ccbd17766b79e6e94e88f478db3566a20cb890846917591a07738328d5c05f7ed4695a82607660f1239661faa9af0368aeb89726f13c2aaecf0deaf7",
+		output: "d8fe402a641c388522842385de98be60f87d922c318215947d4b7562d4ca1e2dbc7ee86494e65fb0bfddfdebdb2ae6469312f95b32c722b2720d64bb8d7cc3dd82f9055b1d89f05b77984f91f94ba4ac79c5129cd7c91cc751b0defc3f2799518e372d27aa683f1e7bbd4f55414c48fe8a3a37ac1f179a1a329cda775aec0d31d75a5a38addb1de67c06bddbedf4c8d87abc18c9f9dd072d457ea29ad4dfb109ce7e99a4a82fbe330b0afbb5",
+	},
+	{
+		length: 176,
+		nonce:  [3]uint32{0xa8021c8f, 0x667a02c4, 0x7a68b693},
+		key:    [8]uint32{0xece401c8, 0xfa805a47, 0x6d572fca, 0x9c1c780c, 0x647545e5, 0xd7ef4c11, 0x91dc1e46, 0xba2a694e},
+		input:  "480387bc6d2bbc9e4ced2448d9ec39a4f27abe8cfb46752d773552ad7808a794058962b49e005fef4e403e6a391d1d3f59025eeb5fb8fbbe920f5361862c205d430eac613cd66108f2f2f0bd4d95a8f6ca7bd1f917eaeb388be87d8b7084a2eb98c575034578edf1b3dafff051a59313873a7be78908599e7e1c442d883d3fd3d26787eb7467eed3a3fb2d40046a4460d5d14215565606bcf8b6270af8500e3504d6d27dacf45bace32214472d525fdc",
+		output: "ab81a9c28358dfe12e35a21e96f5f4190afb59214f3cf310c092ab273c63cd73a783d080c7d4db2faccd70d1180b954cd700c0a56b086691e2c2cd735c88e765e2266cd9ebe1830d63df4b34e2611a8abeeca9c8c4fac71135dafb1cb3569540ed1362ddeb744ed62f6fd21de87b836ec2980f165c02506e0c316ae3cf3d18a862954d9781f726ecc1723af4a730ccc6d6de82553450a52499acb58fb2008969401c45b2f20e12b58f308db1d199b4ff",
+	},
+	{
+		length: 176,
+		nonce:  [3]uint32{0x414e687c, 0xc6fc69c2, 0xd3ca12d3},
+		key:    [8]uint32{0x1b51cca, 0xbc8455af, 0x3f904842, 0x6042b452, 0xcd4dd164, 0xda83f3f0, 0xff04b972, 0xf972dd0e},
+		input:  "b274e61059f3215173ae226e30a92ee4b4f8a3da95f2e768e3fac2e54ddac92c200c525f190403a6ef9d13c0661c6a7e52ed14c73b821c9680f1f29711f28a6f3163cf762742ed9474dbea51ff94503a5a404adbbdfbf4c6041e57cb14ea90945dc6cb095a52a1c57c69c5f62ac1a91cd8784b925666335bbfee331820b5f7470bc566f8bbb303366aafe75d77c4df5de2649ed55b2e5e514c3cb9f632b567594a0cf02ec6089a950dbe00554ee4dfb9",
+		output: "a0969730d48ee881792a3927b2f5d279aba9f2ed01e6b31b92d0e1fb8ba7f35a236d838e0ce5f8654957167de864f324c870864b4e7450a6050cd4950aa35e5a1a34a595e88dd6f6396300aff285de369691b6e0e894106dc5b31525e4539c1e56df3ceedbbab1e85da8c0914e816270a4bae3af294b04a3ea6e9ef7e2aab4da5f5370df2706b5e3f000d88179ac756deaa652a1cc85e80ad9622f1bf91a2776262eb7289846d44f7f8192e763cb37aa",
+	},
+	{
+		length: 183,
+		nonce:  [3]uint32{0xdd315c1d, 0x2335da98, 0xe0a0da0f},
+		key:    [8]uint32{0x6419c7d6, 0xd340f42, 0x7af2f4b8, 0x3536cf42, 0x2f68c6fb, 0xac9d855f, 0x7c4d490, 0x9711b1b1},
+		input:  "ee849039c6cd972dc943d2a4468844d130c0150276f4e0889047e2300c3ecc6792c4527bfe9437dad877eb986e6b1aa9b867d1798c9d314243f0a87ec9ee5b601c2554876c87cbf50df3334a077c4152f8b8fef4a2d301ddbfa90c887ece757c3eb6c4fc1e0212d6b5a8bb038acaec28cba064c9b34f5364cb7f0fc2ac4ef2c7ddde0f5ba17014459eaa78f08a46a01882ebf7c6e409dadda250bb899dc8b3b70e160bbcb4412a9963b174d0fc6bc16383a46ffaacb6e0",
+		output: "3e272ded9c0a5cebe7cf17ac03f69eb20f62996e047501b6cc3c8691ddb2780ea72c21a81888bfea96e4373a412c55ca95648390de740102d661143043baec3976230e024477d134b8504a223c36a215b34164c9e9e1fa99a49fdc56f2f04ea525a6b82997d9bbc95c4b5baeab4dec50061efb7c1a757887acb8b47b142e0a2e61885a2c14c4642d83d718a0546b90699adc545a48129603862a1c89d8e665cde54b3ba487754db6d6f5acf6a4b95693cc569577a2dc48",
+	},
+	{
+		length: 185,
+		nonce:  [3]uint32{0xebb44f7c, 0xaf14c7dd, 0x4543cd7a},
+		key:    [8]uint32{0xce71977, 0x99790e86, 0x6510d6dc, 0x37968ae7, 0x2917fb9a, 0x19ef25f, 0xd282d085, 0x6128d043},
+		input:  "0992396a6f29b861dd0bc256e1d1b7dce88435733506a6aa20c62e43afa542d1c46e28b2e6d8e2eacb7c08db05e356fe404684b0e3a9849596db82eb788aa09258c28eb19e9838f757425b4edef12deeca56e30cf030272e325d4246d6e083219b2f965124963ca91f066d47bf5a8282a011a78b0155aa70038259a4a59135f241fd2f88c908b9f4eef7b7df0f3a1c16a52c009b522f89dabd52601bbf6e3ce68732e1a6d444469480f06da218786cf6c9666362e7a7f7be12",
+		output: "545c05a84b5a4fffd1dd623c8f2b11443818560bdb0c26dadd3b694d4790d294b99059f4127b7cca122c4000954d745af96094ff4623f60db33e994bb6903263d775f48d7047427b3a498c2ecde65bd37bcb8ee7e240a1e08c884c0079cab518f4e1c38ba5ea547f4da83b7c6036e4259bee91c42e8fae895df07781cc166f1d50e1550a88ee0244bb2950070714dd80a891aa8a9f0580a67a35cb44609b82a5cc7235f16deea2c4f3667f2c2b33e8eeef944e1abdc25e48fa",
+	},
+	{
+		length: 187,
+		nonce:  [3]uint32{0x35cb7190, 0x212e9a86, 0xbc423ce4},
+		key:    [8]uint32{0xfa19cede, 0x576ae8f2, 0x58055dab, 0x91b3355d, 0x69d2501a, 0x736323c2, 0x266c1385, 0x134f4557},
+		input:  "3b9efcbbb607fad5e9f1263dad014cc5c2617d439fcd980408f4f9a93acb1a33d1c3a22f38c037e4603dfbbfb5571bc08c4a1958cbbf510e3e4dd19007fe15fad7808369149a9c4db7ca0496f7a600a6f2454ee1cffd5a68d45c270e4b53ac9b77f33a1ffbb1804244f57d2b05b8036fe2cda9efead3d4eff074ea5c07128e0b354a4a11ffa179163933bc6bd10d200804cc93b64575746e94e975f990bddcc8a4335e99e2459fbe9bc0e004ffcd6cac52f48ef55cc0637a75c1dc",
+		output: "631ba7301e33236da2477506ea98d3b732447389e849b68e1f09bd5fd814f40dc3247a1012fa654f08e3dda0c104ee2dff12ecf5cb018644de50d70dfb6c8cc1f5f552e5f1e50466bbb538ad6b98fd37f33fe615c326efc9cc97899b829b007f91569fa9b28ce0076c53daedf9cc0f838e22cf1125b86a6a2c2eb4a45dadea45ad00fb4f054e7d6b09c13ab1dd5328debfbf4f1b70af2b8a5b1d02df8a87d7661473e0c180ba4c815f14db87c5bdc15f11a29d8e0ce3d747d5dcd4",
+	},
+	{
+		length: 191,
+		nonce:  [3]uint32{0xccc941ac, 0xdba45b02, 0xab0d7ad6},
+		key:    [8]uint32{0x9b750752, 0xa627090a, 0x967c95f0, 0xf8ff2c3f, 0x69beb97e, 0xa30b99c1, 0xadddc83, 0x443f9baf},
+		input:  "f28a71efd95e963e5e0bc0fcf04d8768ce93cb55dc73c32e6496022e214596314b7f843f5c7b136a371c2776a0bfbdd534dccbe7f55e9d3d3b5e938f2d7e74393e4caf6c38fa4b05c948e31dc6a9126817fa3d7892c478f75ab9f6ab85c0e12091bd06e89c7d3ca8d9dcdd4c21fead3d769a253919c2c72dd068474ea322b7e71cafa31684e05a63e179e6432fb70661792cc626a5060cec9e506b35d9286f15dc53cc220b1826314eec337dd8e7af688e5950b2316c30516620569ea65aab",
+		output: "1bcea54b1bf4e6e17f87e0d16388abe49b988b9c785b31f67f49f2ca4011ecd2ad5283d52ef707dd3b803e73a17663b5bfa9027710e045a0da4237f77a725cf92792b178575456de731b2971718937dd0e9ea12558c3fa06e80bbf769e9799f7470db5b91476d6175f1a6d8e974fd505854c1230b252bb892a318e6d0c24dcc9ecb4861769cd746abab58805bc41c6086a6d22b951fba57b00c5b78f6dcb2831715b9d4d788b11c06086f1d6e6279cd130bc752218d7836abc77d255a9e7a1",
+	},
+	{
+		length: 198,
+		nonce:  [3]uint32{0x987e7c58, 0xcc839a94, 0x30952e60},
+		key:    [8]uint32{0xe34a286f, 0x4adcd996, 0x97168712, 0xa82dde8, 0x14249e5, 0x5e82810b, 0xb4a445e8, 0x9579adb0},
+		input:  "c1d1ede73bd89b7c3d4ea43b7d49c065a99f789c57452670d1f92f04f2e26f4f5325c825f545016c854f2db2b3448f3dc00afe37c547d0740223515de57fd7a0861b00acfb39931dc9b1681035d69702183e4b9c6559fb8196acbf80b45e8cc5348b638c6d12cea11f6ef3cc370073c5467d0e077d2fb75e6bf89cea9e93e5cf9612862219ca743ef1696783140d833cd2147d8821a33310e3a49360cb26e393b3fee6dba08fcda38d1b7e2310ec1f715e3d8fa0c6b5e291eea07c25afd5c82759a834a89cc5",
+		output: "11a8493cdc495c179f0d29c2b4672997205a9080f596ee3c80d79b55162b1c875ac18eb94bf2a9e05b08024f524a1e9665912394a330c593d23260e6bdf87620c10a48f678693196fb744c49054182fba667c601e7b7ebf0f068e8d69ba004b804fda616a4a0d5350e1a3bd424b8266462be282308219c578569aefc1ccd09ecdf5da283356c9e524e14e69d25b0e19643dab26f54373a7272b43755c3f1ddaee6c5fb9e8e093110c41697e95f73a68c75454e050239197c9fbd8cec76698bd11894ebf6e2b2",
+	},
+	{
+		length: 204,
+		nonce:  [3]uint32{0x851f025a, 0xe6f3c800, 0x85ae7530},
+		key:    [8]uint32{0x2d0dbe47, 0xda05e465, 0x42f6b3b2, 0x7026e79e, 0x9e446680, 0x691df976, 0xf7b23da2, 0xbb3421fa},
+		input:  "37b2dc4b6a5203d3a753d2aeffcdaed5a7c1741ed04d755dd6325902128f63b6981f93c8cc540f678987f0ddb13aae6965abb975a565f0769528e2bc8c6c19d66b8934f2a39f1234f5a5e16f8f0e47789cd3042ca24d7e1d4ddb9f69d6a96e4fd648673a3a7e988a0730229512382caaded327b6bbbbd00a35df681aca21b186bc7ac3356d50889bbf891839a22bb85db4c00bfa43717b26699c485892eb5e16d1034b08d3afa61f3b5f798af502bba33d7281f2f1942b18fb733ca983244e57963615a43b64184f00a5e220",
+		output: "b68c7a2a1c8d8c8a03fc33495199c432726b9a1500bc5b0f8034ce32c3e3a78c42c1078e087665bd93c72a41df6bfa4e5beb63e3d3226aeeba686128229a584fab0c8c074a65cef417ad06ab1565675a41cf06bb0fb38f51204eccccb75edd724cdd16b1d65a272f939c01508f0385ca55ac68a0e145806317cc12e6848b1124943a6b2d99a8c92083fc5f31ab2e7354db3f8f2d783dbf1cfec9c54f8bfcb93d6f28ef66f18f19b0fab8836458e9b09bee742ba936cb2b747dd9dcf97ca7f6c82bf0af6f1b433592d65143fe",
+	},
+	{
+		length: 210,
+		nonce:  [3]uint32{0xaebfd97f, 0xf583442d, 0x15ab2f1f},
+		key:    [8]uint32{0xd3d1cf9b, 0xe43187e6, 0x5071a757, 0x412a83b4, 0x3f27716f, 0x17fdc488, 0x271f77ed, 0x6c4bb056},
+		input:  "68c2c5612912b5f994172720130dff092ee85a2c1395111efa64d5a281ca864d3db9600e685854d81c6de7e8747b92fb7c4c2efa829d3d4c0c9fc9d689e2e5c84c9eae8ba4ab536fb6c7523124b9e9f2997f0b36e05fb16163d6952eee066dd22fb7585925ffded0204cc76818bcead0d1f8095ca2cf9cd1ddcd0361b9c9451940e14332dac4e870e8b2af57f8c55996447e2a8c9d548255fe3ed6c08aedaf05bb599743ecb0df8655152bbb162a52e3f21bea51cb8bf29f6df8525eb1aa9f2dd73cd3d99f4cca31f90c05316a146aab2b5b",
+		output: "d0ae327fa3c4d6270a2750b1125145bdeef8ab5d0a11662c25372e56f368c82c6f5fc99115a06a5968f22ffe1e4c3034c231614dd6304e6853090c5940b4d1f7905ef4588356d16d903199186167fec57e3d5ce72c900fe1330a389200ed61eec0bdc3672554f1588ec342961bf4be874139b95df66431178d1d10b178e11fcbd26963ff589d5d5faf301b7774a56bbfa836112a6ea9c3026ebdd051085f9131132c2700674bef6e6c2c5b96aace94eb2ba6c0e0aef0eefa88995e742ca51ac50af83683b801b7c2c5af4880e2b344cc5564",
+	},
+	{
+		length: 216,
+		nonce:  [3]uint32{0xf9e973b8, 0x2485a6a7, 0x2ea7dee6},
+		key:    [8]uint32{0x96edef11, 0x8cf57f26, 0xb6e3a83c, 0x9ef434c6, 0x4607ea48, 0xace87e4d, 0xa0d87475, 0x3a9c9458},
+		input:  "fed3d1efa309c8b50cb9da02b95167f3b77c76e0f213490a404f049270a9c105158160357b7922e6be78bc014053360534add61c2052265d9d1985022af6c2327cf2d565e9cef25a13202577948c01edc22337dc4c45defe6adbfb36385b2766e4fa7e9059b23754b1bad52e42fce76c87782918c5911f57a9394a565620d4b2d46716aa6b2ba73e9c4001298c77bfdca6e9f7df8c20807fa71278bd11d6c318ed323584978ad345c9d383b9186db3bd9cec6d128f43ff89998f315dd07fa56e2230c89d803c1c000a1b749107a3159a54398dac37487d9a",
+		output: "6a95fba06be8147a269599bccda0ce8f5c693398a83738512e972808ec2f25bc72402d4bcd1bc808cc7772b6e863b0e49d1d70c58fcf4fcaa442215eeb3a4648ade085177b4e7a0b0e2198f0acf5465c97bd63f93781db3f0b9a0a184c3e06a76c4793a13923f83b2242b62511c2edff00b5304584cbe317c538de23785d2504fae8faabee81c5315298186ce3dcbf63370d1ccd9efec718cbc90b3d2e0b0b6aefb3a9b31e4311f8f518be22fdc2b0f00e79a283701c53f6936dd63734ecb24480d5365d1a81392498faf9a1ddee577007acc5f8c87895be",
+	},
+	{
+		length: 217,
+		nonce:  [3]uint32{0xe3bd4c44, 0xa3b75a31, 0xfe92010f},
+		key:    [8]uint32{0xdd05ab8b, 0x5ac7cd1, 0xb8113720, 0x53524706, 0x8e0ceea1, 0x52eb23e7, 0x1c85730b, 0xb33914d5},
+		input:  "d776bee5625d29a2ebf6fec4df94d2b9ac62e8e7c56704fd38a87ee932b787cbc555621535e76ea30183cb0ee30604f485b541f45feb8c01b9750d37fded5cdffbbc34fb90fdc9c7c7ddf949a1d50b796f1ea5db437238c7fb83c4b22c9e491f75b33d84746f1cd10bfda56851b8514ff0ded0adfd5092a66a85202d06bd967485d06a2c56011110da74bf40b6e59f61b0273164744da02ce2b285d5c3f03aee79eea4d4503e517177692ed3bb035071d77fc1b95c97a4d6cc0d41462ae4a357edf478d457c4805fa586515614697e647e19271091d5734d90",
+		output: "60e9b2dd15da511770162345251edfb15cea929fb79285a42f6c616dfde6befc77f252e653b2d7902a403032fc4ce4934620931a2ec952a8d0f14bf1c0b65cc287b23c2300999ed993446eb416749bf0c9c7dfe60181903e5d78a92d85e7a46b5e1f824c6004d851810b0875ec7b4083e7d861aabdd251b255b3f1fd1ee64619a17d97fde45c5704ab1ef28242d607d9501709a3ac28ee7d91a3aac00cd7f27eb9e7feaf7279962b9d3468bb4367e8e725ecf168a2e1af0b0dc5ca3f5a205b8a7a2aae6534edd224efa2cf1a9cd113b372577decaaf83c1afd",
+	},
+	{
+		length: 218,
+		nonce:  [3]uint32{0xcdabfd50, 0xd10d5b99, 0x9e160a85},
+		key:    [8]uint32{0x8231a4e9, 0x89f33c8b, 0xf96b11b, 0x853cae9d, 0xf6624a33, 0xee9523ee, 0x28bb7853, 0x688ac6f8},
+		input:  "4f57848ff5398e61bcafd4d4609bcd616ef109c0f5aa826c84f0e5055d475c6a3a90f978a38d0bd773df153179465ab6402b2c03a4bf43de1f7516eb8626d057ae1ab455316dd87f7636b15762a9e46a332645648b707b139e609b377165207bb501b8bccfa05f1bf0084631c648279afdf51c26798899777812de520f6a6f0d3c7f3ef866982f5d57f9c8d81c9a4eabb036651e8055a43c23a7f558b893dd66d8534bf8d179d8aa7d9e8987cfdaaa7b5a9381ba9c79d5c1161b1bdbd30defdd304ee07f19b7ba829a0d5b40a04b42edd6407b68399caac69069",
+		output: "e096cc68956ed16d2dea1154a259e01647913eeea488be0b54bd1816c781a35e161772ae1f7a26b82e864ade297a51cc9be518641b2e5f195b557ec6fc183e4e5c1fc01d84fe6ca75e5b073af8339427569b1b8ee7fcff0ffa5e7e6237987c40deec0abf091c06a3b28469c8f955fc72e4f3727557f78e8606123e0639dff782e954d55e236448f4223ff6301accda9f8fa6cd43a8d6381e5dde61851a5aec0f23aeca7262659bc793ce71fa7992f80e44611ae080b7d36066e5c75c30851306f0af514591d4d5034ecdf0d6c704bfdf85473f86141c9eb59377",
+	},
+	{
+		length: 219,
+		nonce:  [3]uint32{0x67de323f, 0xa0442ac9, 0x9d77b1d9},
+		key:    [8]uint32{0xca8d33d4, 0x834349d9, 0x5e68d581, 0x99a7c30e, 0xdc7f6038, 0x697e8b63, 0x284c2ece, 0xee3e3bfa},
+		input:  "046a61c0f09dcbf3e3af52fab8bbcded365092fad817b66ed8ca6603b649780ed812af0150adbc8b988c43a6ada564a70df677661aff7b9f380d62977d8180d2506c63637c0585dcef6fe3f7a2cf3bbb7b3d0df7769f04bf0f2e3af9439ab7615c304b32055aea0fc060890beb34fa9f90084814b6ed7363b400dfc52ee87925c5b4a14a98e3b50c7f65adc48c89ddd6414626c5e0bdefabab85c4a0e012243e682d4931be413af62fd7123ab7e7774fcae7e423bf1d3a31d036195437e9ea8f38aa40182daa9aacf3c9f3d90cc0050977c6065c9a46bcca6ba745",
+		output: "cd5a6a263e3ee50dda0e34c614b94c3ec1b14b99a2f4095a6b5715fdfc3449fcdf8a09d1ae02d4c52e5e638f1ee87a4a629f99f15a23dd06718792f24285f5a415e40f698752c697ee81f2f9248da1506ce04a7f489f8e2b02e6834671a2da79acc1cdfb78ea01822d09a1c4a87ffa44e56c4f85f97507044cf946ccb6a2e06e2917bac013f608d75ee78fa422a5efc9c569226bf7068d4705fde3a9fad2030256db0acf9a1d12666e0acf9f5346ad62e5af4c01a008d67ab1224b3e98278d073116ff966cdc779fb3aff985ec9411a3eefa042d71dd4ae5b15d5e",
+	},
+	{
+		length: 221,
+		nonce:  [3]uint32{0xa36a3d5a, 0x1747a05f, 0x5440eb4},
+		key:    [8]uint32{0x2d701ee6, 0x143d5a1a, 0xbb67b9ab, 0xabc88ccc, 0x20baad8f, 0x6507e48b, 0xdb1e1b39, 0x9e521d80},
+		input:  "af516216f74a6344cbe458cbba820f7e25c0b10aa84b790da2ee6317e059171076d7246c2878be83fc00c200d546c007f849e4c163d52c7b0da31beff4abff481be3266b92e668cf4dd1c84d9d7b3e5191dcd6ddb51d17d337621046e83e9ac035fccfb239648bc3c6fd340fbb50707e5a33b3ef439d292192d0e4bc727690c61450e5a28789e5ea50e746bc66d039493e080fb70e9ae06d89004cb71de8178941c422f1e9862492fc9149a4864ff52b1277b9f5a63c2f16e9adb5263cf65a034a62ebb0f1a385d2681c87a35f1c45670b4edef1c68fe9544fcf411d95",
+		output: "b22ffd8f0e549bd3e0206d7f01ff222f92d39b41cf995a331d5ef0cf5c24bcc3ddb36e64d351b5755400246fe4989b5f912e18daa46cdd33e52dafbd2872f16e94220b56315d72c1dbb1525fd34831d7202970c11711ff36de3fc479407c34fef0aea86e172f9beb0f393194355b9dd59625639f4a6bf72ba571c229f2fb053c1114e82793deb2dfe8232f1a327949689d2fb2820662dcd2a39a2546c7df12b3ff7e87e58c74badf568cddebd3c558f0f7874c834c4b8aa988653f138ec79620f5e3ed737690928a30f981dca9f2920ac7307607063b40f87c204de47c",
+	},
+	{
+		length: 223,
+		nonce:  [3]uint32{0xb92be022, 0x1e1257c7, 0xad7c01e},
+		key:    [8]uint32{0xca1dbb9c, 0xaadb9504, 0x77b8a95c, 0xc50deb5e, 0x2dbc0fb8, 0x9e654bc2, 0x94d8925a, 0xfe9cfb66},
+		input:  "a3d70bdb509f10bb28a8caab96db61652467cf4d8e608ee365699d6148d4e84d5d93bdabe29aa4f0bc8ee155f0b1fb73293c5293929eaacdd070e770c7cccfb2de120b0c3811abeeddaf77b7214a375ca67d618a5d169bb274a477421d71a651cfb9370bcf7e0d38f913754c11002089cf6cd6a8de1c8a937fb216591d57b37efdf3797f280773950f7eddeb9c3385c8315ff5ff581c64610a86ada7ff6a1657e262df94892dff9fdfb6e958d101f4c26296470c138dc4e1ca4bb565b3ff877a7f78b3d11d64b7c24e27ba6f6b06f6e368f5ac218cd5d11b815ab0987678eb",
+		output: "646314264896a6e25601e536f6e783d465b2ead1e0be4422bc9cc8eacabae4a749ad533eb28091be8397328dcfb34c92006bbda930ab070ed7b806095bb1c8f476350e7b08ffbd4d7d6055c8defaa8deff9d54f5215c2d7db27ce09e08f5d87a859145ea3126e2a01882921c3fddef3985bd451bca44063258390aec8ec725b07d064314fe43a9c83e9287b47616dfefbf539b82da209aa08a6d3176b7e3b4be4a17d44e581280a684e4a64414649bfcea82b541729f8178b580e8b972a89f5b8c4f9b68205e9396d8ae5e81873b61da074080fd44c52d50fb0880ee9c35da",
+	},
+	{
+		length: 224,
+		nonce:  [3]uint32{0x5091927, 0x661c75ba, 0xc23dad},
+		key:    [8]uint32{0x2e00499d, 0xafdc63db, 0xc3c62efb, 0xb4157a19, 0x84ce8b13, 0x85326279, 0x2ee71e9d, 0x318721e4},
+		input:  "f48b5ae62f9968baa9ba0754276cd8e9dcfa8a88e4571856d483ee857b1e7bc98b4732e81f1b4421a3bf05ab9020d56c573474b2a2ac4a2daf0a7e0c3a692a097e746d12507ba6c47bec1d91d4c7cfc8993c6700c65a0e5f11b1ccd07a04eac41f59b15b085c1e2a38b7d3be9eb7d08984782753ae23acdafbd01ae0065ab9c6d2a2d157c1fc9c49c2444f2e5f9b0f0bbfb055cc04e29b2658b85d414b448a5b62d32af9a1e115d3d396387d4bb97ba656a9202f868b32353cc05f15ae46cbe983d47b78ba73d2578a94d149e2c64a48d0c1a04fc68baf34c24b641ea0b7a800",
+		output: "b9af1016275eaff9905356292944168c3fe5fdffd9e4494eb33d539b34546680936c664420769204e91ead32c2bb33a8b4868b563174d1a46108b9dfe6d9ac6cc1e975f9662c8473b14950cbc9bc2c08de19d5d0653bb460bea37b4c20a9ab118a9550bfeb1b4892a3ff774e8efe3656adcdf48239f96e844d242525ee9f9559f6a469e920dcb3eaa283a0f31f5dfac3c4fac7befa586ac31bd17f8406f5c4379ba8c3e03a6992a1915afa526d5ed8cc7d5a2605423ece9f4a44f0c41d6dc35a5d2085916ca8cabd85ac257421eb78d73451f69aaedeb4ec57840231436654ce",
+	},
+	{
+		length: 227,
+		nonce:  [3]uint32{0x5d6d997c, 0x9d623987, 0x5742de36},
+		key:    [8]uint32{0x57b2a5ea, 0xc5bdd68b, 0x99c7b0c6, 0x26aea960, 0xba5c75f1, 0xa904cf6b, 0x685031de, 0xa0f0e99},
+		input:  "b39101601efa2ecdf41878b0fd920a3005ce709e4ec2970abb76e32c232ea21069f81b246eda75aace7555ce8ae203455d3723e684bd671389300e353eec0d2f499d10654fafda2e7a69bfca7198eb172249167ca8864b5d5f58d28723090ec86e251a1bac0346d52fd81f06e0c05429e0b2b895588290b7d00878a4da3378eb6c7e61487de2b318fedf68fa7ad7c88ee746827c1f60d98c7716f3f9695c5ffd4670f71a0fa78a1fb554ba482c5de83feaed7c65fc71acc9f541342eb8f7622b12bb2cfa222fa2ddd8b3ed210ce442275afa3132c8a0e17dd504ecbc92525c118952be",
+		output: "50eb5b21c179a03b9a822f0075906a3ce4acc32486139f92635c7d834f69071d5a6dc0e15ed06a5cee37147071d59641d140a82ad5815b954e7f28e080c3dbbeaf13943d7b7c66d49d51ba1132eeadd4cb7a7e7d726d08d95f1578d55519f267f753f3e16ff39504a87b2286d8bfba0fe6bc28887b466bf276453a82cdd0abbbbf08db0e1c26c317d50ad9b8dc09cd621bc566d362024e8404739df6468869d2125c58b25d70e392f5e75924c4341be81c263915bb514ad436fb24c2c67450e84f6d1b72d1a02a3310c07a7814d930264fdbbf5ddca7067e18e8a44faa87169b7f2e35",
+	},
+	{
+		length: 233,
+		nonce:  [3]uint32{0x75bca707, 0x89f6d1f4, 0x2a6f657a},
+		key:    [8]uint32{0x949f42cc, 0x2b5d3c48, 0xfe0be473, 0x17ac92aa, 0xbdc9d9dd, 0x74f9df26, 0x26487508, 0x7c7b41a2},
+		input:  "0a42f63b975ad0e12a1e32615813dfd6f79e53ce011e2a2f0534dd054689f8df73a8326fecfd517ff7fe530d78081af66c3a8c7c189eb9d9efed1e5577b5512d42ef1fe273f670ce380c64bc62e217a7e410a8ed89998344e29301e4e053a3a3cf7e71587fd056a6bd976f16e157476a06997dfaaff32172dd84190570621f2221420c0a0ea607ea756e9792c8c0e7157c95b89c9490e20b750ee85e4c27c9b8f409e848ec90afcad33342010bb9808358afbcb3d9b094127c38c243a204e76899677079758e7cbada9a5c18363449eebc07bab516a16372722403a046df85c7dd2ffc804c54d38aab",
+		output: "87a47bcaa1c1eb8e55151011c4f39af4b9e108a55a7124cdcf66d0dee727306e6971f783b038bd6b215f530cdbb53e17975742ec304fdb3792a88b674504396978c6a5e4a9c87a7c3ca430d61165c1a3f6162eeaf38c93e18b6ccb6a595ad428cdc98efef8f84463eed757a72ffd827b71c0579fcc1f4baa11812be2bc5a2a95df8e41d04b33343df09ce628c367d1f88488f7a2787f013c8e76f0b9257cee777ec4adc6df8c5790e41ea02da85142b777a0d4e7c7157a48118046935f8888b5352d1750bf00b92843027a349cf5685e8a2a2efde16dcf5e1c1ed8c779bb38cabfb42ec4dd87d58273",
+	},
+	{
+		length: 234,
+		nonce:  [3]uint32{0x5003a4f7, 0x40bd8cde, 0xfe35fb25},
+		key:    [8]uint32{0x576e49d9, 0xe84e9df, 0x9f227a3, 0x437c9de0, 0xc46ac8de, 0x1a6a2d2b, 0x42ab7684, 0x4253fbb6},
+		input:  "abeff48fa082dfe78cac33636c421991b0d94c3bc9e5bd6d22763601a55201fa47b09ce60cb959ba107020213c28ae31d54923d1e74ab1d9ddc2762b2d23d8c6961d81068230884a39682fa4b30676ffec19319362c075df0b879a0f083a67b23597bf95c4bb997fae4736479cb8a9c00520ba2f6e5962d54c313c576180d17779ff239ad60f1f1373627770d50a1c49718b2b2e536846299e052f8c1a5d3079e91cb1b8eac4661daac32d73b3b99e2051f8f694a61d1e9d3935f802921a4d979b6ade453cf30d73a4a498a6a2c5395c60fcf271d50b4967ac12b0d7bf818c2679d552e9b3b963f9f789",
+		output: "a0d11e732984ad575570ed51031b8ac2d7b4c536f7e85f6fce9ef5d2b946cefe2ee009227d6747c7d133ba69609f4a1e2253d0eb59d1f930611e0c26a7c0cf2d2ce7ccea6e079eadf2eb1acf0463d90fb4b3269faae3febfc88cb9fb0873d8b74894506199394c8e44a96e6b479bd3e045749cce1c3f57243abdb37e67084eb573cd820c6cee424227019592a027e9da8f7b8997bfb292627a986f83c8fb8d156a91a12a8b52659cf9272924631745ed3a2453a4c2d87a167faa9104e799c715ed597bcb66949ab15dae29a86ba147507e8d8af66e96c09c53caa053ad3b79d9ed3c0c6c00169eaec3a3",
+	},
+	{
+		length: 237,
+		nonce:  [3]uint32{0xc6ae48ce, 0x26f0906f, 0xfd8ab8bf},
+		key:    [8]uint32{0x42b82c50, 0x7f519e0d, 0xcbb95098, 0x6f75e532, 0xe2c9f61b, 0x5a4af942, 0x2679777b, 0x6a8e1c9c},
+		input:  "a77b7a5870335b9145fd2e08ec898ba2f158fda16e8a2661a7a416857b6ba6937b4843ecaa79d3635d28383af80290842de9ca0bb621ee22b7fd6bf379922741e812b1739c33dd6923d0607826fc84d46bbdbd1fe9d1255f56a167779a560a6eed1b9c9579b8f771147df467e67a070d9e9ce8ad92dc0543d1c28216c1dec82614ac5e853ed49b6abac7eb3426ef0c749febce2ca4e589d06ccfc8f9f622ede388282d69ceb2fd5122ba024b7a194da9dffc7acb481eabfcd127e9b854be1da727483452a83d1ca14238a496db89958afd7140dd057773ea9a1eee412875b552d464ba0fab31239c752d7dd3d9",
+		output: "b330c33a511d9809436ab0c4b84253eeda63b095d5e8dc74803de5f070444a0256d21d6c1cf82054a231b43648c3547aa37919b32cfd9893e265b55545be6d7cd11d3f238ef66c3c278fcccb7dd0dc59f57750562cb28da05d86ee30265ff6a3991a466ba7e6208c56fc8862e19ac332e5fb3cbcc84e83a6205dee61a71acd363a3c9de96d54070a69860c152d4ceb9c4b4cc3b878547b6116699885654b11f888dc3c23483a4b24fbe27c52545c06dd80ab7223d4578ab89bff5f9cbf5d55b19611a5251031df5da5060a1f198226c638ab5e8ec5db459e9cd8210f64b2521a2329d79228cc484c5065ef8a1d",
+	},
+	{
+		length: 244,
+		nonce:  [3]uint32{0xea38678b, 0xc41eada, 0x3381147b},
+		key:    [8]uint32{0x268fc2ac, 0x21297e86, 0xdf9ef8cf, 0xd4b45234, 0x2a95c4f2, 0xcec36ce3, 0xd5fa38c9, 0x7dc43790},
+		input:  "322d634bc180458123e10d0509870b54e0f0a3a72a2bd9e9cf44324c7a1ca37dd6adf9db1fcc8dadabd881f91d47d93b58382802b42ee936802fac8612ea4dd9eca5f215935ea9ba6233b9c8bddba3385861de669d95c888c8977851cb305db577a4eb2360f362fa459d61ffc8fcaa1502905b073bd8e9567ac7cff8e5fb1002c55641a3af5fc47ac0131fae372f073e19721ffcce9821e0241d7fa67bfc499c8f100e050d39bd4d7cae4557d208629603ec4a007852762ec1905d0e81b873510fd334dedcd9c288eb8415db505913af06bea94d197ab627d58f6a9944f6c56247595fc54ae3f8604aa37c3466f74561131e11dc",
+		output: "edbfb1090987762f75eba2439d746cdbefe8605b8ebad59e075d28b54edfe48813ccae891f6ed655c5ab5211ba896fff0c8e09bd1554aad987dc53f355d0822e9b0f524a99a79c68a9f3b4e30506cd725b07be135e4540078be88dac64fc545c433837b96a924452f6b844291c4c3fb5f8cc94f06d9f19dad7fc945f093020e82ed19f9eb3ddff68b813629991d1a460e5455e1cb41cf23bb3d96fdb6b96581c3bf9ef72814406329bbbba5b835e7724c728cebe88efcd996dea71d0fd5c53e081c21ce8b3764738d693e390fbf8e0137a716760fc9cd2014cd9bf3fd706bc3464d1f15803606976e96b1077cda0a62921ff7c32",
+	},
+	{
+		length: 250,
+		nonce:  [3]uint32{0x883ac584, 0x8fb8e7d5, 0xdf07de66},
+		key:    [8]uint32{0xc7747e47, 0x853d88c6, 0xbf9aa631, 0x78f16480, 0x7c248080, 0x15ff973b, 0x31528a40, 0x629686e5},
+		input:  "e6b8a9012cdfd2041ab2b65b4e4f1442794fdf1c3685e6622ce70f80b9c2252ba6d9e6384d474a7622053d35df946a3b19408b3e1712da00525070279ce381359b542a9ad7c07750e393e0834593777352c1f7dbc84cc1a2b1eba787377d2cb1d08a7d20e1393d44022107acac5d765be37f9075af02e4bbf8e60ceb262aa34e2b870cc7adcf54329a667249cb4958393bff4f4333338cae45cbca419d59e605aa0cecb1241080339198b9b283e4201afc07360b8ae2a57b0b9b97167c315f03fd7a87a00ae73f91ca560a1505f3cdf04576b9aee5ea775f719916f1e1942ad5311c7f87153f8e62855ace3f34afb08d4d7c7f4fd2bf83e42f76",
+		output: "fc2673c80812d101bca7a2e0e105fa449550e695a016596f5c3cde11fb7dc518b94fdb74058e634546a726c37896110e1d1f9cdeccba1c89958041061ded8e8bc2751ec6dad76a305e70c57f9c81a5a65b5116390af4f7bf7053a03ec13f5d60a58cc5ba61f8c46ef6d2d291de490082dcfdf294aeb3a9414d64e4bd6497d4625acfa591627bfd98f0aec7e7def71515c09942db6911d73b96b4bd2d6df03bb729e945d71549d40e4bc401e1f73baf263a74280537692240638619f92645a5ade1eb8151191c7ff8bd715b3c1cd667e69745b806e16d46d9aa680a7367b8fb45a1598631cf3d44c1f5cfcd95bc8dafdb65a2083905a6937fcf21",
+	},
+	{
+		length: 256,
+		nonce:  [3]uint32{0x79cd7a62, 0xae619be, 0x7d96d236},
+		key:    [8]uint32{0x7dec8e64, 0x9f12b14, 0x6c70df2a, 0xeae0aa0d, 0x27b1ac14, 0x7a00d833, 0xe63c0aca, 0x189438e2},
+		input:  "0cfd93b195e37dd15dfae83132c24ed5bfce7fe6fad4064b213b2c31a39e39ddad2f977e904c9c5b055ed03db46fcdd845bbb6ff0ab5a8c92e89295b6801f36ae63eba61fba24a3858aeb36f2da226b23b24d7b2c7d2670f23a9a1b60db85c0ecee584bef1b00e42d10ca17432a74bbb220d88356d82c850da4c09dd5baf413caf8f9479e02a330065fb865489c0f59605d56146ec8434182345de2d15e2a1dceeeee2fe94871d41913f6788738947ed9849ca0ae985e3e19a97bee82b96feeddceb196c9b6012264661945981c279f43db9599a4ef01116f592478619690daa64387290484d21e8d2444751194e1f361fb37f04014a3c7e4b409e5c828d8990",
+		output: "0502848571d1472ff10bec06c1299fad23a2cb824d88bf91b5447c5139500bd837a2fddc629e4a964e84907c1e6740263f1fef4f5ed41062982c150d9e77a1047b7d86c0e191945e8db00ca3845a39560857fc9e0e4a394eea4ba80a689cb5714c4bab7124ffdbfa8bbb91c3eb3caa1621f49dba1eea3ebf1d547ee337f9085638a12317b86c11aa1525813445107038942fc519eebdc1b98d313ad822bf0b94a054259aa8cf1be4b3a68f974269729941747f9a23fa5d83453071b431dac62274c24f6a32248b0785ff90aad5840fadc89af0aef7553d9352cfb00d3999ffbe28cd9fde7854e95710f4532b8bf5011e518c93361e58d22a2302182e00e8bccd",
+	},
+	{
+		length: 268,
+		nonce:  [3]uint32{0xb7581e00, 0x9a1bba92, 0x64356674},
+		key:    [8]uint32{0xdc2c9fcd, 0x5e50de1a, 0x8546466b, 0xc1b49b21, 0x36a670cd, 0x2887f367, 0x2fbf4300, 0xf90a0374},
+		input:  "0d8d864010ce8df1c0179cf0236dce1c100f9c115eaa5294c24a2e1afa27f9d57ebc18f00482be0218d44262bd4db73002ff53c6388f5e333470aced2a42a73b376686c8d02e05ece27cdd8b1e3f675c715981f8b656d68d0e16227b529cf881d2433e4371fbcd933eaa72346e77e688ac80ee95324512c66a4c16338cf38c941b72c21c3d01e005a07c0eb436014fb1ee61806de7e96842ca3217ab8c7607d609dd2f637f9fda8a85cb0549f262c9e4a955c384319a6ad2b696e2593d7d174f5ddb98e2a8d5d12558c18ab67571e9a0202e91ce26d720cbe41a3a6a4f309296ca4d9d9a59a9043dd2e5a707ed7d5034023d5ea06ab14b39b7852e5c984848d5670c6f2f0b189c2a8a4a4bca",
+		output: "d2a5693c9d503a8821751d085a0837579233e65b691366e4a7464481d22800e786939349f721a815f28b4e47c8889f0814fb95d592d1185e45d6dbcac14ffa4f1d6c79194f2f7eb7323439d9607edf80f01e3a968b483eb93c01d9cb9d3625d21d66927e7aeedc1d9bd589560ed2b61cbed5ad0e0310c8ebe140c64c67d4909c010902d5386efa359ab60a9573493d3e5d8761cfd4023eba23de48372032d4673b5f6ad66cd0dfab02a73aa81f269ae88fcabb3ae9cb09f6bf60fd3575a3046bc6843f444e1e9fb9ff9b991620344fb99da68df09496b40f8b9dfc34e830a87f65710940603ebab554d36e8b4c9228bc9c26c07b828f34cdfdd40b161717236ba325e8c20bd018b324345e09",
+	},
+	{
+		length: 305,
+		nonce:  [3]uint32{0x2c641fcb, 0x5170c7e2, 0x62a23688},
+		key:    [8]uint32{0x5aed5915, 0xc5c4cc18, 0xf0e51574, 0x75d894c6, 0x1b7082d1, 0x5d2ea1db, 0x709fd24, 0xf5f69898},
+		input:  "07c50a69e168e388caf6f91471cf436886a3de58ef2c44795d94fba6538add8d414d84f3ef0ac9377fd5bed6aa6805a695f3a711025550bb6f014893c664e09bd05f4d3b850771991fc02f41c7353cd062156243b67fce9c1f0c21eb73087a5de0db0578923eb49bf87a583351e8441c7b121645bcb64ef5960fdca85af863dca7ebb56662e9707d541513bc91bf9b301431423b552e2c148e66ecfd48045ecb3a940dd65694d7fc8bf511e691b9cfd7547fe7bca6465b72ff9f1748723c4eb14f8bc1efb2fbc6726115c597a3881e0d5019335daf2e5ea8796c2a8b893ca798c4ef2639465505c4bd492bf7e934bb35be9b66c9f35730736c65fa4c1a2485378b9d71912cb924634a8e0db2802b75728818dc00fc28effdf1d8a05e4de4608bb6a78bb19c377d5ec77dca1b5ad38fded7",
+		output: "3dff5fde2ca24bf419e13cb7d12368e70449d41f2aa22e4b567f5cbdbcf3257975e44097deb180f2621ec36acf375dad3b7a19234b9856dc6c7842a7f86be00304b41a8c1662a02e8390346cbd0ff6be7bc1ceb821dbd805ab5c93c9c6ea5093249b5dc52081cbbbe1b326e831ef3c6c42fb791790086d1586f7daf031e70a71b54e9134f942e9ce229fc77980eb80c985ee0c5965eaba375d156f9b423b0615f4ca6fd77de28e28f35aba327e4f1b75725730155b7b4d6c5c264bf3d9dc9a16e7ededcc261add8c666278bac5cf0b3275d6d6678060eae30bbf2ce5f63e6a53a450b65aa0adbd1c90cf045f5ddd9700c2a99c80586c5244cf4c08035b6ff630c82cec3a4fcc83860e987898b42fe746939f8b37c814f8dab65de276e9784fb90f0751d3ba0826889e1e7e4fdbf8a90942",
+	},
+	{
+		length: 430,
+		nonce:  [3]uint32{0x99b172cc, 0x91056d0, 0x48057533},
+		key:    [8]uint32{0xe6cf398e, 0xc3c56066, 0xc5ff194c, 0xf6d2d8c4, 0x6d1d8908, 0x63e62065, 0xcca485cb, 0x1eb03dd6},
+		input:  "3ddcd3c00014747903c95e49f64258615455a0b26c5070a9532382a9bbd18eeb19c9fe1a902f5c6baf544c5938fc256d310a9332223dc3c54a6eb79a4b4091c3b01c798d2800418863f2865c1cd8add760e445588576d4a6c945e1d6d50dc913674daa4737ac94d84eb0ff57cda95df915989c75adc97c4e3c1c837c798a432ba4803a246bb274b032db77e5c1bb554a5342ef2e5d3ff7f102adb5d4e282ad800ccae83f68c4bfd3b6046786a8cfaa2b63c62d64c938189b1039ae1a81ce5c91530772cca0f4a3470ba68e4e0548a221eb4addf91554e603155a4592dc5c338aa0f75a8cc2822b318fbfba4a8f73fa08512132705dae792eed6b809c251d35cca60c476406d964187b63cd59333771e37367671d0ccb393f5b8bde77bebc133485ec5c66bdd631d98cdbee78a3cf435d2f824fa2f9e91e89af28b2e155df4fb04bbe4ce0b6162dcd8e81ee8d5922ebf9c957b26c343a0396d91f6287a4af9e11b7fbb5a5a5c1fcdb186365a20617d4ff5037b0bfa97b6213a6ebcf0b78b81c65737378787b255cba03d715fed4addc2c70c1fb4d3ab16f2bff287186c26a164dae2fe9dbe3c4a2e1617f01cae79f",
+		output: "ecea5fc18dc4aed23359cacb8f79a457512e0a27d9816f353e315519d2b2faf74d14ae8ae5e227b203823998a47a050c363a807f45f610942fed4518b8091b88dff8b2af8fb6552eb654c85d2b6a918bcf56fb898392941d983b1afd867ef840e12313059ed3e4d217498dd511563a939c3c536fbbf8e019deed29262f0a655fc680b15939475e0cee0ce2e8bab5834f7354b93e2e0958a5bc608fab369b6aee3c9d73a6898e402484eac7300150517bbd137bf55762897696a3dc4be74b0c141755ac8f2f6e59f707b1690c451a774c46bbe195d826a6784f8d807b78f8ebc343ecacf37cb9b1b2fdbff6a1237b5098853d783e77515c419894c2628f8b5117042294ee2ed58a33746f9e79b13fdfaa25a75fc95340a89076e786e0ecad7de437a9a3fb3092146d255005b22895310b1252a3e34572cf74665b97f4adc30dd0f34e3216c7757953a4b618a775bbe68f9e0922d75afc80a1379aaf1745f2263afb6f0b37553d9c984f1ef781ea75b1980c559c77565c83f3e0bd7a3cd7cdb594658beb7e5eb940633dbc6ae2f50383beea676cb6c814b17b1d73dd133f544da88ab371415889ead21803c1ffe3f2",
+	},
+	{
+		length: 449,
+		nonce:  [3]uint32{0x2adb4a6d, 0x33d00c1c, 0x10a0193c},
+		key:    [8]uint32{0x8bd707df, 0x70212019, 0xdb685581, 0x9cdbd1a3, 0x7db9ff1a, 0x1af119ee, 0xb1d8c0ff, 0x3c4a22cb},
+		input:  "93ce72a518ae892e00c271a08ead720cc4a32b676016612b5bf2b45d9ae9a27da52e664dbbdf709d9a69ba0506e2c988bb5a587400bca8ae4773bf1f315a8f383826741bfd36afeae5219796f5ce34b229cac71c066988dbcae2cbcfcdbb49efcf335380519669aaf3058e9df7f364bfd66c84703d3faaf8747442bdd35ac98acdc719011d27beba39f62eab8656060df02fab7039223f2a96caac8649bc34da45f6f224f928d69c18b281a9b3065f376858c9fd10f26658ae21f5166a50fe9a0d20739402eec84f5240ee05e61268f34408089e264e7006a59bb63eeaa629ba72603e65718d48e94e244e7b39d21d85848d5f6f417631f3876f51b76b6c264356d7d7b1b27bbac78316c5167b689eff236078cf9e2e4626a4ae8bedeecbcaf6883e2e6e9304969b4fc7a4280dcdc5196267e9bb980e225fcbf7a9b2f7098f7f5c9edd06f50c8791edaf387ff3e85ff7bee1f61e4660fddd4eaf5ab0320508e3ccaa9823ae5a71faa86bd76e16d862d83ed57bf6a13de046a3095a74a10c4da952b3c9b8fbde36048537f76eef631a83d55d3a13096e48f02b96a5a8da74c287a9164ce03ddf2f868e9ca3119ec41f0233792e64086c903eb9247dbae80e923eae",
+		output: "bcf49d62dcd1cff9dc37d7096df0c39031e64ccaeea3830fa485edb71b7fcf2ec709a4b327ef9c7d4ea2b35f113a8485d4c236e06b3baccee30e79c6c08739fe5fbed59db30479b56dfbe584a5d79b169b200430ed27072137e940a34170606b31f22095f2151b4d9b901f6337f991a23e4c8997a1ebf5105361fdade1c889b8dc9565e3b33e0bd608c39d725becbb60da8a797186fe0986736112da3d09906442364d6e253e5b27fd5ad72e877c120ea7a11d42b19948f0df5ddabf9cf661c5ce14b81adc2a95b6b0009ece48922b6a2b6efffdf961be8f8ec1b51ad7cfc5c1bca371f42cdac2389cbddcdc5373b6507cdf3ffc7bfb7e81487a778fcf380b934f7326b131cb568bbaa14c8f427920aa78cc0b323d6ea65260022113e2febfb93dcfce791ab6a18489e9b38de281169f1cd3b35eee0a57ed30533d7411a7e50641a78d2e80db1f872398e4ae49938b8d5aa930c0c0da2182bd176e3df56ab90af3e46cdb862cfc12070bc3bd62d6b0387e4eee66d90c50972427b34acaf2baff9d8a76002a20f43c22ac93686defc68b98b7b707d78d0e7265aabadde32507a67f425cbd16c22a426d56b9892bac3a73dd2d2c03efdb22ecc6483f8d1ca67fc7d5",
+	},
+	{
+		length: 487,
+		nonce:  [3]uint32{0xecf15215, 0x45e31add, 0x56499d31},
+		key:    [8]uint32{0xf5988496, 0x49bcc2df, 0x7b4ba3c3, 0x5d5138be, 0xd6cb466b, 0xe98c82f8, 0x147d3f27, 0xc82389f0},
+		input:  "f72bec13b0f0b6f2317118f14c2a0d8e963b1bd49ae7584e710dbde75bb1e30c79281847cb822a5f3ae4fa56825e511212f17f0d293cfe80f872e6992d304e9283d08ce65ceeacb003b36a862c91282a22536e0b9c19953512a1bf9e20d3e7a8f1a2dff45dec0b9b04c592e88a7814540cf636a024d10008463d0b3aafbc4c9359889149433ef173124866aa6f53526ef3b3f2c630860ecdd08ffd9fc050e95da512cc87f812f9391085cdec5cc87258b8560806a52336d612da7ab05e0f60566b950904aa27c975a48c7d78455728c87f9b53aa4978374ab9592e12c22d9a760e26eb527133534ac5bbf969596b71cde8b4ef3587fa7ffa7116834348c275ad4dce68ab3397521ddc8e54380129cc81b981f9b32db20dddb0ecaa0f1ff7b06495a42b4a800a207b8e9ca38794e2fa9f40546e0e3aef7b5236d7fdadd72b1158714a5ad8d6264df1e75120088e449b9e911eddac59f1f19a795205ab7532783a93159876133b3fe3a518475a545fbe8dd2ac143f33c35d98e3ee13b63606b1e671917ac3ff9412773a3ac47b8c6627b8ba9dde6820f4f16c2ed9cb7d7086cfbb0cf2d7533eff253d14f634ab2aad3fb4289b9a0bb667a6fdd0acd5949185d53f1dd2b96ff060bb44f872a67259100669e6eaf1a7e2b11dd5fc35792db0c44a1127765934a068bf",
+		output: "bb618ae6b7739a4dedde1dbacf864b0892b93dea3007237d2f6f23be0718bdd29321e6b0fcb6a44dacf0f5c53d91e16165997e2302ae7ebc2dbd02c0fd8e8606a4ad13e409a4e807f331cf4174171c5fff23ca232192906b4eefdf2ffb4c65af78be01b0ba7d15b4341dd5a2edd49b17db2812358c8af0a4a9724e0169f50d1d331936bc2400012a60849876c3ead52cc9fe60173c9992f83f3e41ebd24fe3961835109612994c7620280539d483f91ef9a64c16032a35612a119589efe6357fa35b19531274576e304be75bc7e91d58015792095bb00ce4de251a52b946554366ea7ed9ce9317020ec155ae0071e022af36ad10eda5d671e5090c136e381cecdb8bc179474fabc7dab2d8a134772976cf0791b6cebe2333d34b4b8e2b6b2eab2b5dc7c6a08a583d091df64328cbcde36bc1b81095d82c741a1503c55d833d551a855e098166c5efffb8e4146e32e54abcaa85076ca6660abdfca9e82824217b5d3f23f7ff3455872bc76751480c1a8e3e725365c82fc135cd3713cc0f1ea733754142f8c37716a2a4fa8a6b898215c287565325774c2510df6b49e78cb986853ac5ca532c9a7e2bceb7c0157f60433f29fe29009343d6035d7b5892c77f821b644590615dc505604501dd218dcab789e6f0525387919cf25c7c6d62a8979e39d346decbed2657",
+	},
+	{
+		length: 511,
+		nonce:  [3]uint32{0xba68c47, 0xbc020097, 0xbf7d14a7},
+		key:    [8]uint32{0x3bbeedde, 0x6e8f4d6c, 0x6e27cd72, 0x140ff360, 0xc891efa0, 0x4aaa227f, 0x733cfef2, 0x2b51f1f3},
+		input:  "96eb94e1adbcc0646440c8824a2fc0f2c4b17d9cbddbb8ba8d9dbd6482fbf7201c74eb923153e0138b2f6f182f9c3d5656ee40bb7c26a01740b5c7d125261d4e4197614800aa152b402ba581bfbf4288e73c9ef7e7e37491212b921420eaaff880eeb458e3d0aa108b01b53492c97e328e9d10e3220b924351d583c00e76aee9325d6b89b1f162ffa30b386b37b5eaf4dfc25d22987dde4496158818c4d8f19ea300fe140be921d3f1abdaf9ab8946833a57cda5f41f995ff80e98b0f10f7afd736dd33438dfd395547f11563056078ff8f7c202aac262955f0ca5dae2365472de40f069028104ac552ea5a45ff2773335e5d3242f1e62e0e98003333dc51a3c8abbaf368f284536672e55d005b24b7aeba8e4cef23289adc12db2213aa037c797e7e753ae985568199cfe14cf1704fbca443e6036bdd05859e3583897cbefe7a0cf268b75d554b2da6e503ee04b126fbf74eaac0ebca37e84ab9c726973af780fe2bc9869fe67b7d9e4a04062ee535b2c1740d1347224e211b5cd37ee14c3325f40abee930eb6a1634986e756b3a1f86a3d7ee7184d95ea948506d8ab8b23f92ecf3eb0586f7a8b1bc227e08a0e32ca75ca4eeffc5c0a2a623547788bca66f3dc2c48671e462544d52a87d34307a7f111aeacb7da50262deab33d9f29dd6b47c3bb555be598d619cc66be8c4b74b01772725268a43d467f39bc565e5efcd0",
+		output: "590965d18ebdf1a89689662cfae1b8c8a73db8b26941313006b9b9bd6afa6a57149d09a27390b8883069e4fc2dfcf75035def1f8b865e24c21b1a1ed3e9f220d7b48046577b661bc92d9888a912984ad415ea2fc92c9e37da0bef5c7dab11495c612c27b5babe6eee28fd26482272fce69ca7f11bac95251735ad808365ac587830ec04105304f8e440a4da47d30e788718da4282941c9c76f18de4f954b8be750b54cb1145489edf273625a0df9a694a23fe7bfea12579b53c3b2a3de85705568cd7e603f3b8beba9a14cad9979ea283a8a291d3e1105b7f890e2a569804d9b7dd4c7e50bd0dcd11223fd7247af77f04212ece1b98c238d2fa0386a994bc502f83dcdd2e5a0d45b185155e1a395d91726d383c2c198fff1590e983c65ee041638510787c8c59c2e96f31678226a033e027bb40c416b73c3dbef31affc93a659c8ec7ffeca313fd5283a80533b2d63941c8f245d22b160c5fe57c5fa4b759c407b9acd6d9c4f80f244360b9acd11e2b43d4af757e16a6ef9d6756df39ca3a8a235e74351f50b2ebf54df633c8c400fd80b41b07117676d486377095660f2f20f62c034563b4560b473a8f4d6a740306d2a822fd8bd98012a840ba9b1709df9a0d61ecc305f7180fd764e334045d9a8ca23cb8036c05616a8b21fc488429ba4168c59dfa231f0ffa668a3be7b16583df1a55bb9c15d51660ddeca730d66f7a9",
+	},
+	{
+		length: 607,
+		nonce:  [3]uint32{0x9419df54, 0x4593f2a, 0x71c06dd6},
+		key:    [8]uint32{0x7b517740, 0x41e86353, 0xed629408, 0x5fe32cea, 0xb06bc5df, 0xaec9b350, 0xc00c2a6f, 0xb3aaf44f},
+		input:  "be3f309c6e7b89e1ec4a855cf161156d09f8a04d5630534ee19e9e071e3f4603f23f0c59a7b7f8a32c4c203ec8c129a268faba09abde7b61135c6c37fd091e2d695f0e242488098ebed30c7d321f4dcef0bdd23fa85a53569868cf2008bf4d2ee7a12a6673298c7e797321b9f4559748223b590e6fcf17aa72251586b01181cefcd32c6a1a20a0fc27143426f6572b1aab0e7301e390cb857f912d78d5153906c698ee140b36cdc72693cc019cb7add747ca3a07b2b82a2332bfa76c962b186ad94209fcf590ed0f6a73b08a771a58eb9649f2f1da4f7c385da83d50c939231f745514d14b0920deedd9c4dc6d2e547f83643d13541870875e52c610372b14b602e7a47f0b3721cfca60ec68e2eee91f40ceba2d0fdb4ebe19cb1d1ab170726c9e600030454ef355f9a40033672be520e528937f38e7a862a5ae50cd94f667cd015a72ee3f91b1a09031bf4c207e0c516b2e7a4baedf373f1ee71843e560741ed3a3094d2b513e2248caf27ce135716f6887d9f1fe5b11e02c12c989d29054ab183a3f55d9b40d78e12ff56edf936ab966c7c3130bea472b71fd69e70165a76afbf720e2c1587a77943b35acfd81b2ab6f39476623edf3663024fb84da8057ed3a361e9533caf9fc58a5e4897e4bf84f58ed063b5c353bdca3792952eec0a1404149ebeb5b17cd6350ab3e27e44e40fbcb00780d001a48d0365d534ff830553409919608881e665f83bb5cf0736d728c41cc4e985c377f89ee1186303d0d76bc634875ab3ebd87059969f24b0464ae11967bcc47f300a34e3b917b1affceea716c5ad9abf1aa3a1106e2f4d006514dc62cfd2a52426968f2f3991c9f9d8fcd",
+		output: "e4032c01bcece73fde73961ed216820dcb44ce20134678c98afb674bb03afec2f4aacbade7f87a32fff57ae9213eaf0509e9d9db1313b06fd1df53561f85896ba627cccd2d0e2ae4f24f5579bf02f6599f5e63412ba084cf53a5bc9a8061b5c029b755329fcd73f629fadd3bcf6cb4c572fea86466cb5159d19eaaf0f44c3471d0323bc7206bb514ed8117a61c6d98d44faff6a83716657531d965ba3efbcf067c452e0d2807db3423958d9a4421886fe132d7c47e82086db9507616b67f0051dffc1a49ecce3ca8e4d5f5af15684cd8837a471430ddd333ea0b6ee603b7d9e702692f857fab060ccf26f2a8e61dfd3b12923acca78b83a6004e4ff09113becf6bdd0bec3a449a195559dfeafd4e2a79ead5ae3c993a15ad9b1a2ce818e18edb010b7fece9aa437d85ba9841d89026d6aac1a3a6ab6dad932a26d7db6f3664b06d51584cf4d22a75c06e2840db7292798306e4d39379af85a6bc8dcaebb5246e07fadd5e336f122de0ecb99ca24a971701a1f43bd69933beef6e52d299b132e7510caf27b99739e32bd272afc36755ea80cc7ed3957d91325584b338d15b19fe554ee70bee903babe21d0cbecd49235c70a3a4f516ce16761d1cfcd70bb4b9c7c73c359f3fdd0753d6c1ac1a1463142f18266b6a9c84675f247d56563646fb2c8c3b6b81944c2ba2b76b685ba5ea40cf539bcf3850a8af3e0a69c0b38164de520a3bea82b91f67d36bbd87877b5be7f06c2d26b2dc747a26a51f51fe293197db0e91e6ac617c71ddc6edfeb7db8f067ac2012268deb7e5f00a640c1bbec5c4c71f10f921071308cadededad5c90e72d744d0bf790b043fd35729570889ebe5",
+	},
+	{
+		length: 682,
+		nonce:  [3]uint32{0x17cebe90, 0xeffe259b, 0xbdf9d4ca},
+		key:    [8]uint32{0x172d51e8, 0x5b80f5c6, 0xb9c9e438, 0xa56119c0, 0x62212323, 0xf5386589, 0xde7079a3, 0x669e643},
+		input:  "0aa4fbce7e1774f0607e7ea01fc0e6d210bb283964ae75e180a9f6ff3d2c4d50914bfc32bca6d243eb33551521d54d66f377fdc1d31974ece79b157905ff7e7a9b064f349727ce37c83c15ae13df635c3e6b4baf994d9aa0bb90b06c6cda51deefda72c97a2993448e654b746b216d2b949bff1af5238558205cfc3162f1d7a020a919db4d4eb44bcf7b269d4df57e24133d1e540694b9148444cee16e64035ef006a6079dff449949c1b342991f2a27f21c8bd74ccf4bc944284a46e9fd9f9bfd4b95f80c05553950fabbf5e5aed6babb8427832266aa4d175114de9127ff6ee848534d6dd5aa6d2dc361319863cdf32cfb1b074faed17d368964393352df01fe8d86af0e994bc9dac315f7d9efa7bef47a16676cdf17a535ae71d399c4c11a3a3ba0491e8d41f419685258a4ec7d1ae588b3ca341719c0827ce5f5a653959a8671844f2d0293c09bc7d35497ed18c160fc7b6d073a311b621a7a37f7ded1df3d73dcba1821278c9e17a191997fa4dab0802e1ee1b468e91e4272c4569a17dc0b2805b980bde798640aa328a3605abea1865083d7446e960c27f69d32882a2a2295efc9c440dc203872373411925f8839715e9441d31dd9cc14bab09a3e03b4a63e14db3039d58725796326ea6327f189beecd63955f1409467c81f4691ecfe9f0ac5234f23dfb84e3199e415ee7b4f67189e8857ff6cb3f64c2ac1b554bfbd679a6ea8491cfd69d96d08ee2744d9103e0b044212560ff707974b1a9043e1f2c3592828fde8ab5e993652c00e2b3fdb19082611b67866ece6c4a2635f87e04d2136d679f632416b03ece4d7e9406f3437163f4fe0c8cc7b87d487f6de3b3022665bcafa847c2b9199e1ba9af7deb0e29b66ad41688d03a8369416dfbee6d03526adb3ebc4b4f8531d73589499a3010b5309e9d9d2f5a9cf347983a92722dbf6c4f0bae8aba57b37d322",
+		output: "a31f9a532f35f20ba604a9ab9989260e5a4ed04e6ecfa1cb9e0e1d16943906acbbb4e761a2bebc86cad0ce8b3f26d98b455e4b0835eb8b43791cea29fe8fa6e5187b60198142059bbce98917aa2957ae2555bee70e6e9e21ff6197a51ac2ca2952c413efec4d9903a2f6883e88aebe7ca8316831f6a8f2cd0e486319b58dc8db862779adff98b7f35c33faa53d56acd7a81e0feffc286b728f3a11afab7cace4c30b1a45780276b1f0ab89242410d07cb1191c7b9da5d09db7c9a729d91ac3ed82f4350f2871a12d125ba672861d1b0af7219c360a0e023a8b7c23fb9d72631c72e032c097118d90e5db0576586d8224165a8376fe8d04de93516848e7c2653cb4f7d24a971ccf4f16c527ea5b4153fad5fd5bf473b15806671854507bf1a6d9e5fe4a6f6ec977197d21d69a041dd955e199031f895adefd850c8b0ae327ba0c18ca1783560e1ff0feb2f659137e34a91e9e9ff04fe3375b7db6e4326986e6265e5fef00297f6ae627c7563846e531762748fe8d0b6baff17acf1e6c5cfefa35a95ef634ff96f83f16342a6c62311fc653d314f8a6de109356ab7801316e69a48834cb6325816b1f66d5c67d6e9c9cbc8e1a0521fd6e4bf77a7d2609f99c9579e143f530677b99d198a97620d087f058edf35eb7271701ecebb8bfde5671641ed21aeee9e7db06b932e0def91be93cf2955159e9666c770cdffa03886eb6e98dfca8f91ff5cef1927c0f82b9226d65c68d011416cbef802c264e34244ead7a6ebbe28a510a37e1276f4f3cf27a3944a08aaa23bd321092761627dae20dc269b6150545c75e995cfee0a9bcedb1ad8b364beb8839fd5c9f7984fa0a08a1a354aebe18f62acf6d6664978fcfda2ce6fc16eaa2cda5b835339001b3b98d3a407a3e18e0ec2da6ee3d1448c1ece2ed67c3f51f01e76ed59f0e61102b103a3c65aea94275e8d1f0d331538efe",
+	},
+	{
+		length: 768,
+		nonce:  [3]uint32{0xb1c9bd09, 0xdbe6497d, 0x16c73b95},
+		key:    [8]uint32{0xbf9d9e5, 0x2eede668, 0x631dca95, 0x4233e36d, 0xd83fe644, 0x99b11f89, 0xef055717, 0x1ae9695f},
+		input:  "e097b1e8dea40f63714e63ab3ad9bdd518ac3e188926d1086a9850a5580affb592f6e421abc617c103479ba39a3924eea1c0bbbb051614c4b5003bbd5fcbb8093864fc1c130748194d6b560e203b889b98b574a98ec3e0e07cb2d9f271ba7794e5419123b4f2ebc7e0d65cd404104868905ff2c38d30c967fe9d77ebdd4b8fa836c3b0ad15e3e70e9a28236d5593e761e694b047f63bc62c7b0d493c3e2528c8af78f56725172ac9416ec2bdc54de92b92a63f9ccb61e686f9249c7cc337d99b2160400bb5535eb8f8eb1e3cafcbceaa821c1088edbacb3b01b5bed977e702de747ad00268ffe72e3d877dd75816db65b5459607cd1b963fe43bf2405ec223ddc0de514d59cde74f7522dc72285caa3eeb7eae527a7723b33d21ce91c91c8d26bf36eeb1dcdfc1e9e475c1565ed9c7e64ef601874a4f277280a5ceec26717e9385aee8b159379e3feed7952b87240c942970d63351259aa7a286ddb4a2620fa67565c92f592902e49422f1eecea2f44d1c0bbbf54a9e5612b86a9549aa3e6639a924c7bbe2d3c1b5669da73c0e2c6f6f6084f54a912ad2635d0141c2f5ac925414dce0da09ab8f86eae2a7b7e48741253189e5fd554d5c04d9807ac6ffd8a4f8229a3e8ab75ca5c778bd7ec5a5c02085faba9792cbc47f9e9311f3444e6544359769e1b3eb4d42ac8923ec94536e1a44497766b5da523f5763749dbc2738dfa8e13c191dfeac56c7614a96bd3ae23e4e6e5ac00be851ac9831108989b491eaade62113c531385ef3e964ce817c8ed0857adca946467682c2f4387fab2f31ce71b58370853171720268459588d5d216faca58d0bebbd7cd83a78445d9b49e83ec2cdb59b5d760880bf60532178d60372752b47d52562b316c7de5c74af9cd588643002d66bc6260595a540d2f82cf2c07fa64e0cdd1f79877b6a25b0608c735a7d35ca10852da441fcfb31061fd7e482a0989866f9eea8b0b39c3d519715c1c2766c3ad99f041143cdb36557ed647403458155dccbb80c3a365f0a85b1135695648ab67ac76b3d219c7b77e49d735c72ac947b1d7eeb279beb9d2602aba7b36ca",
+		output: "7b6e07e6415660affba56047b988f4548b308e7a642c76791f5c3742cc4cb744cde48fc30e50d458084e06c6dd29a52cb4c306a69a493a17c0838d14b107d07b81c983a2dbad09b80f087ba48465a8beaae5b16e8093e17cfb9e84ea3bdb9af00889268a5c01ddf25af434de56f65882322432aa275fac8519e317ef4d89478f29182143f97350983050f5d37c4b518611da6fa2aed7bb73e614231a194fe17c9073e377fc6ea0aa491e15ca54808e0536c8c3f1bf657283f807ebfc89b55049ac8fb86f89f17974fcf0afc1a2c690c0442842d0f4af9ee29dd960e499d1077bfdad4c0c9189a6e83799bb585acdb853c1e99da7ce9c7eeb9bf431f8d364d0ea80b0a95a7807f196c6ee69fe90e6d1f5d23e5cb256e37e65826d7a111f2272884d6319f968580b3164b2697ea6556816cea3ca316651fe2fd68dfa905d080c28622606f7d24da216289fa2c54c6f42dc244ecb047512ace62f0801f2dfad8f0218f45e2b3bbac97c2176c842398b16dfa1fdfc9a68b7b5a1e785d2a0cc592bc491f5a69c81127b758ee02c66b81674d3135c5882d1dc89dadcffa06f4b0644df5c7fd65c72611d79be7ad637edd6fc38b39946aa2a2c6d08ca9d3ff9a8ffe2e7989546489539b1a623fa937c468e59e0978602526b4367de277526895aa222fbaeae2084f418c5745d8ee844da0baa47f592970c14cf710f49539c12104a62baddb3382f5773dd18c83ecb238ae2e749a51584a38e394ebadd175bf5c3cec787907abb1d94af70ae63d3b7d8d5ff254da90b78ec8fe2ea95dfbc6e3e69ecad856c9e54906df8fe39859f2014b74dc3ca0ee2a957001939d37a6c0b489bd3f1658b835a57b24aa282c23e875c9e67e6eb8b32fe44e7d7d8e285d85da0ce1b53990f9fdb5e2e74728e433ed2c1044df9e89cb9bb316c39fc6fc8bcc74a382093926a288170e857d6b7f47858a4c2d05c74263dc9e8199332d0179687f4a4cdfc80ee6737300cefba75905b22d21e897f887b67aa3051877fff11d98bf96ca5091bb225bddd5eae697f3dfb0efcdb788ebf6694b5b39dbb0d4bf9427382a3a58f0b",
+	},
+	{
+		length: 828,
+		nonce:  [3]uint32{0xc7e503e, 0xf8110ddf, 0x83316c8c},
+		key:    [8]uint32{0xfa2d1cd, 0x4fe7f905, 0x2b9e4c1b, 0x115bc881, 0x2922bcc5, 0x3f60aa25, 0x13c26d31, 0x2096af63},
+		input:  "0a1064714f20d9e47fe53250ecfec759f4137e60afaf65755f4709a483504c3855833b6dcaf7aa0180fd735fa9a73d46697f6c45004adf12452ea4c04a720fd7c20b9783b74b8b3ea0c8b1563d5a85f44af8afd7d91ca6298ca22642a684f66e365edd6f6bdb2dd32dfa13c62dc497fb341b86f65d40655931171416e23e3b2623c0b4a67d448877b6e3d4e0fe284034a10162b2b5e21639047036874f4bcde22b145b5f18aa8ff32dec81e6a5ac68b3c30c24bd8fd3b8e098a1cf202e2ab2a3bb66a9393222b9f7384653cda7707f00bc3c81e9591fd040a07d3629410c2db78781a4c9db3df5f9d648162f1b087974f56a89db07aa21ba827e3864a1618945b2fba06853a13c35da2909f5013feb313bae09870b8eab904024adab0d6ac46c1a1499791b47413139dee59db676949b9e9ab8d3d6abaa954ec2a9fc83953c91b483c3b6bd6700b96484850734e72e3710a1b379c0d0698aeaf68f13a0d317bfd689471e3299288e7a383a58522f0daaff210cc4917fa05f0b8ceefc2afc46148a05a100d30787accfb4da094e61ea6b58f132692aedcabae928e53c2594b01507b8fc2d0a85a1d111d1f4de0b95258281ae01873a72606753b6f878ecd8c4f613fb3477710d260f0bca0d4c06f675ab7113eded395f88755a98a0ad22b4a002cfe9447c4e39eda13738f4eccb9c13367ebc2878257c4647d31b67e5e32b6a77f23e9593658d19c0a40e8a7228767afba1cf23072b013b2d76ee66e42b57bec2797ce3619c695a661004c8129cb5c5d6a2836be22483f3b7e40bf8ac5535bf6cd065c4821a87829948c88163cfe3c0f60cea4e7ff59df4cdbf80064b2d664b39487413039999b5e86f1d467b12682d0cd355e9f7cd980e87d584ddbda89f68632d3b8fd6bc3b80205d7feb97a46842b093f74aa14bb21accda7474247b5e39ac76ef75e9b5b52b6a829a7e2297ab88fb0eb690d54ab1af2d7437149a6202035ce15f1e6c6267458d62677c263d83d3f8119af191b7d766582620e0f08b411c996c25ba6a32c2d73f592e789ed662e94103329bfa5e6573f1116ec04438997f3e4ad91b4123b570743455020d914bde2d8417fb24671e6db261732fb89dda1a36614b095529e4f97374c9bc0e55aa577bfffa663c816ca9fae3472e0a",
+		output: "b00a7caf5359c5bcebe590e6bab9aa03370050c55cbd45a257f4869937e922a15f2d38121b1493d6b5dd4a8a47d7b4e5cb049d396ad84ed421df774b0408b6939f18ebf5cf83f48c540affcc2a885967bf4bd222c42904b8a73c4185bde3f97e874fad25b46714235e60c9ff53ed2975c9c85ebad0752249e4b627ffa41555eb9074f63a5f7d61d207d2ce11b2a9fa23a13a0832eccb91efa2afd8d9acfee94ac78a733fa156bfea5006da1d0127c32aadbb75c015b68c627903e1c85bf3a1a9f99c6cfbdbb5c871f7f9661b78cf5e16d819f53e9930e201d4f58e69bcdce77ec5b9b1d2cf206a71f744342273c26b9abc71303c20df3d51f52222893d803fc8e0e0afcd99ee1c7f95b48680403566f7f9e296d7ccc0ec348b6ad515af58d11fd82c628ea29ee6a5d67aaeabd8823addc01a078b04313af73105d4ce4abef8e6ee8ce649640a19678292d4f1017d121549fd2c19ba6cdc0b613e512bc9551d759c6d38aea7e35c0847a142e273a16bb1495e652f9668b97801ba3f6d9931c0a1efaa4452e15732dca1ca9cb45ed289e0fd08d1cee1cdcc9dfba8d0b2562b0b1a180f4ee69d63573222c8d4789bf0d63d2a201a70c7b27c84e620e33e8a863cf49b784269a51ead3d4ad26f044d5859988d5485a11533ea805f5a8f6313caa6b421071a34f57170fdd8e4663e9a4cdcdcc1ddaa9f6e651fb365cf827667b018ae7d028c7f96295b2b4f9eeb4b361b48af86463a79f50b107ab0935e3cec3f4f203cea801ff95fb870d2c2f0e315dc8a6a547dd3c390a1f5403917315164bd2d40362489b389a54e8dc0ddb83e6a43a26c65923e6f76ee0ee0e3a33b0a9066620a01f0319e20b9f1beb3910ad962a3000e6aacb0ae57f3f6c5e0315be5de93edcf0e45e0e47332f9daf7f33e6e8bf1929910b78b8f88ca12bf5519a3217b7554c8c8350cc314561d580bf67a3878e3979430d070121a5e070a3458742e8549bda972f603222e2b30eb8a49a955805307e6e02f8c60a08188f69340e116422458d4a8841f46a78c833b1a822e3f6c9c97422c918f17c36175ca4b3d1c081ee4b175b4b07bf101c3836eb5b9e3cbd08a89b4a1c50edcb41ea8ea6ceb1532f5b842715d50dc21e2499e08c373d3dedb96bb477c8802ab7aa957e0b5810f38",
+	},
+	{
+		length: 859,
+		nonce:  [3]uint32{0xeb02dac9, 0xa7cba06c, 0xc24764c},
+		key:    [8]uint32{0xe9414a57, 0xd5e29546, 0x1a5e2f4c, 0x806e4c46, 0x48098d1f, 0x4351ca1a, 0x53ed97c, 0xa6a495ca},
+		input:  "00fa3b13b5cfa9b5d65a41cc2d3c420518802c22c4582873f1ad52a22032d2cef7c975078b199787e852fb1f914529f60d1cc854e5d6d547216dce043e0fc94866bb2193343c3a07fde60e668266d1cee3067c6f2ce0f9f63456ad08094b6c7f515f7ca90caa96494e2a6835ba1f3f166012ad1ff6af6b5f8455d5c26e72402966af9066ca70ad027eed23b0eb02c751195064a62283975efeb29bc5993f83360d012a2f5275ac758a9e8fe458fc7cc0673e6b9e338678f0faff60a67fff3784c3054dcbd95d1b00ed4c6156b3831cc42a2ccdeee55541f228b88e6c318e2d797c6fc035ae12868c4a4e3843b5b25a530b1477dec3f5ac27644476b5766e0ee132d833f9a63200eb0980bf72c3666150e567e01e3e1f469cf36beea65946fce714a3f354983e54ca4315b57ea35c5f48bd5eada05f49db1004cbb39888ebab3afad62f6509abad77ca8c4ff28731c7ae545e6876c8f4a80b6cc26928ee05001a9764694b52edd605e182d5a3a5fd192bff58aba90f57e4debe612d02cf6f08af33a78ebf8823bb3eb46d4da25b7dfa15ad436c380633d3db3d0dc4dfec6c2324d105e7090e65342b554854e777b40b5dab8125a58e8b212364ff88459a8466ff5ae661034abc8286a78ad5aa582e2dabbcd7a0b0cedcb9fd5f0bb8c3bef9117f2ca6520a72b94e528c1a4a464398e654995d5f4c77cbabf2b204b96a058cf1b38284b34e41ac37b05a003ed51be9602050f21c6b9326714bc425c1e22833da95a6e77571691d4dcab4ef9056c4c7f85d5b445b902eb375b5164c6bdf629ccfd4127a6c024bb6c4da0b6b08350432e58f8229e04e2e76f704be17d36e0c04fcc7a98f721d4572aa7f66ae8e9664300a189bc3862da47b60c8b33424f6d577cc10f4755f36c2a6decc30ba81bf48f96616ccfcfb74965d6bdcab82728bb224c560d1cfd7a175413ad1c14c734746be3b062b4e7514e9075c688103515e32e3335dbd272a315024d56f4ecd354264da9bc712080657b2b51b06dc7c4c441d9858935a4c3e6b207bde38ea83bba4c6854b2bcf914d758e0a174c0528e0e385c7cff355c38db1c22440369141e91266824c59f1ed23e7d4b99d31b0baa7bed4526e24259dbef5c9ae275e97267b756645f804c274d65ac7ab0f7683435bc2e4f24075cd1b790aa2b53fbf044e8f2092bdf0dbe88a582ff8f8de291e8220",
+		output: "bea32587095caac661c3ac49e65654b282192b2addf5b9a403aea6c8bd0096291a0a66ca4062acf1da91fb5749952096ec63ab652ecf94c29807f0aaac939b6896edcd6f0cd8dd8d208b906ef4d7a8766831fecd6ce98f4ea0c34fa9a5114dbeb23c2cd6d3aa962e39b18cb343c24e65d49fad0a0fb50736f8d2b24b011108932484399f4c4510ac9a5e6bc78ff0b450e67f87b49f253b99d95d6294e15a9934fc8b89a5913c08f75d3516766fb0f60f82e2b2647b4619991c78adbcf548c07c0dda30c629349d84f298313c3e629e03760b1cf860264205a950d6fd86732a6513827f72c0dff5aff96f7203464f60849c1065beb70f282cca1334f6f6c767dfff94f063361f592e85597de5d313eaed17bd533db24818d9ba9aea2afa797721fbd19eea7b8d46bbc4b9dc0164636d2e754f5e9e8c04e2a381096331731c645ea1f613a37bfa9a6fb2c6307e9bacacbeab7f5672163ff9742a8115049bce0269d7d5f6f35787be031dbee1535b0516ec0b46d12f5833cde5f2cc569edcdd20993e9776aacf48ace7bfadf79065f2803fba6b2b27aa622abb7ae023ff2b27b727f509f313f92026392485a5ed4fd53b2e22b2d2dc1538ce158d34921214638be30ae054a0f5f1d4f9c590a2d215ac2a5b23ed33871ab26c8bb6db7fe9d6f51e527c9547248a4e9734c64658b22893f4f6867a35f18e2bbfd7d62142025955cb51af8e40b6fcb91c7e959cea2c92022c87c29dae107a306f41b00e73c7bceef8cb070e8f9e830caeee463170e919cba6eee63092a5a7ee33b74db09cdd022fdafbcd5d524253a29a103ba6f4d668d31d18f867557871c0e0258221c3050d57c18bdae4cc4ff8da0daddb5c08619be127ee76a317b59a9d8e67808603a1bfce6b4e0d070082b283bf9c0e6ef8256208e482f3e2d1a40d30807f60a868e2279dfbc3586d44ee25fdca3505cd39fd469c2cd03bc2f921d22a8346750f346c919e7247301c1c8a4a3ddb8eabc6e80d85cd2459afe1cbb4851ea2c86b8075e0fef3177cb074894410ecf681242fac62b5fa4ed3a10ddaa595427851d376cf69e350207b667f7aa26d003f1ec739a8792532ebd93f3cafb1fea40d227bcadda2fb6da794cea3371240f257f80b1b8a857ea453b46938397c1f4b303a46257750003a60666a11d03bf2afb5c71e059933d617288891733b63784bd9c662234f",
+	},
+	{
+		length: 985,
+		nonce:  [3]uint32{0x3c2b47a4, 0xf614c813, 0xa26f7014},
+		key:    [8]uint32{0x39bd3d18, 0xc9aacd67, 0xcb5485b5, 0x20536a22, 0xbb22ac87, 0x1c9da580, 0x7d996b2e, 0x456fe461},
+		input:  "01847d8a97d56e55e12f89adb13c8c0f9dea5555e8dc61171fbb8e181f6cf846a4dd68b2c75335c0896fa215bf7f9eb7e398e4520aaaf33461ecfb61051f43d43569fb75fabd79d319bf39469f951e4da7932a74624c46d8d26a9499c701c00d3dea57a6f65b4c0f33b568d13989340294d17cd005b26d89cf6fa1c88e7b6ef4d074291fa8c117ae05d7c785459ef4561c45af63a811e9aa1c31b69a5bdac2356d955a0f579791247a757a691b3de447a53619878397cd82a74053f06da3574045bc856500ec01fd2afbc64d8dd283ac876a50e9396f78c424ab157f481316fd9c90cd899f5aca46dad32c68f1d64ea7f1c4bdb994ad847072609bd89adc2fa8382a5d573b680533640b8321b6adf27926274660b2cbaf04fbc9a4fb17ce8957c38c7bab1aafd5bf7263171e47d2e1ae5cf0494815642209d303dba561754479c24ea01a573c9083b68acc49907b1748924d3c6a82feb9417ca932578c123f9db35521c0d992565f7396f0c23e436289c1720e4e7c6e285c04a8159f93e06801334e523b18fe188355cc6a155febe64ba053e6b5d1cc87787fd5ae68fa86d8c51868b9f6a9664cf0d56aa6cb8463362bb671e6b8423bcbefe2a1a0acba3f135496736b5cec5e329494af46aba322bf5d1cc108c98298459558773a316e09b0bb960a26f4b0bfbaa493b5f98a0e522b6203c471b10e662abe9b9e60de2a1517843933add02017fadd62608383ad53796159f3d21b2c8ed7295802ca79ea65d550114ca2bcc7f7c3b4c6709fffc3c2de00da06e83d8f0cf04b8c8edd21c0fc11a0b2aa7f6adad255fef25e5c0a9d59546e97446e1fbf6a51a8ea6cad54cabfdd19cd10d7d33ff0549b710557e3931821dd8809ab0a9d3aaa761a01ae0f2e378906672924d6a1b12fb1cca7bed41f31974b9917a05de60c32796f502e7035a2c01cb49bc8e1734b9fa138b81b4dfe19d37f5942dd1b42f03e1e5a6a046ecd457174150e17dd148e4bfea44b72da35ef42a7251244700e59e702033677d42611168fd246e1b18b9a464b6c20fc7fcf6360cd00466ece059a69d7d54a4f5565d08799f85dd3c849a08ba43415077c1c0e5dbdba52bb3167ee99a11db551f0260493be1dde58d2072e8c02251f4f574b6e115cbb6136dc2c3fbce75fdcefe812d9c07a91a89088985a52cb1fb9f6cef80fa30364706414175e42c75e8e37f6e7cd028c99f59caa88c49db5b46e8d6301bc39034013718a9eeef5506415016fb21d70e46a03b4c5ba72f91dd9321ff5e210e5e5f7b0723a3bc4bb02b5a74c1f4a63aa5a993a31f79a768fe8033c9abfeb4deb536af1054be02d8d1c4a6a0fa75f3eb787d57a03b7ae994fb1b54b2c43b230ce32e6245d944b3cea4fa6",
+		output: "785dbea5d1e50af4743ed5fd2209e441fc7c50bc7f6fd9cc7f24654c619e2606178dcbbd81a1f94c1b3176837024098bd31326145be326b32fd9277a55a6fb38780c8dc8b471a3184379d90da4aa87d80b889b1f4d8d0755c1704a526b99ac829b8ad157ca54b2b05ff8b2917e27b0c147ab54add9a89fdcad7b93ba1fe2d5be9de88b68a5324f1b42943e45ee31c4ef783ec9e2337b3f2834b10cf452b313fafdf0c03719140f64060da0a565e185cb8e544e1c185ca230ff2321739a285abe8be4be0ce76678a7b0902a77a645194de49fef8ff64cc464ea25e1f1d72c775e450f08ddd7680d27a4142879787b198583d93b84cd87fd5b4063d92d13d9c9cb580c01fac0174686a18f64e6fa0b3589624cfae04aad74950559bdf92b2b199c60cb04013aa0ef56d1f9ec5b7e968f6a83756ecc9cee7dd8b433f64649f948df5474a64549e71e46fd8bb16568d21f5fb67f5ed555f2b8aec4709383e8cbc45b9fe47c0434178ad4c6d0d42606d6eef0e21d0370898d1d5d646830a88d5f024094fe9c7a2003ca13d20ab7cd748dc11a22f578ddab416f3500eff3d89fc177b46436108e2e2c7973910cb8454a01c9e9b98f966848325444b2ac205b1ed6919fa76aaf63717574761b7f62b10649357df49f85a845a30b6acd57fa202fe58673930ec59399f537e9682b1f5f6f409988789a8e0c1f803478dded14b40d3b6eb3109758efeb6a7fe21f41c4dcc8027258da27ad74010839dbfdf8fe55050511f85c321e653f76e55f22248f46da529a380c6b1a16a19ce73af9715545c2cae098dc42dd61248dbcf7b295f4dc6b8930b41baeef677156c534869be65e723e1aa0336e8be8a3b138f840c9cd63bab6d9d61f239a47d8cf56258544e6ef65edca27069f7a57f087a7cc021fa1294b75c0c0f1093c025e426e4f041ed5187f358402676d5da5fb6ceba76a178f65c8c3046f258531c165b8808bdd221c59ff56e3e06247576e144aac01ea96a07f1be15d7a2b0b3b6c259a9133f8a50b56154ecf9f61022f470027247e6e70e6eaf7ece5e324ec8f95667ffed10337652b119e7cb8d197e306e81ea251340b9fb2c33aa230c0a16e1ca783f9344b3acbf413acd96616e6d477dba90e39326089934bc5ca6620855cdc442e25bf8b8debf335e16e7e25cceb68659cc81b13a507fbd9f30b347126beeb57016bd348fe3df592d4778011664a218227e70d7360d139480500b7f6f84153e61ca4dea105875e19ce3d11a3dfd0ad0074035ff6a9fac0ece91afd8be74c168da20c8baafcc14632eb0e774db758a3d90709cddf0266c27963788c35a842beea8ba2d916234431efde4bb32fd7e1cef51dcf580f4697206bbc3f991f4046360aea6e88ec",
+	},
+}
diff --git a/libgo/go/golang_org/x/crypto/internal/chacha20/xor.go b/libgo/go/golang_org/x/crypto/internal/chacha20/xor.go
new file mode 100644
index 00000000000..9c5ba0b33ae
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/internal/chacha20/xor.go
@@ -0,0 +1,43 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found src the LICENSE file.
+
+package chacha20
+
+import (
+	"runtime"
+)
+
+// Platforms that have fast unaligned 32-bit little endian accesses.
+const unaligned = runtime.GOARCH == "386" ||
+	runtime.GOARCH == "amd64" ||
+	runtime.GOARCH == "arm64" ||
+	runtime.GOARCH == "ppc64le" ||
+	runtime.GOARCH == "s390x"
+
+// xor reads a little endian uint32 from src, XORs it with u and
+// places the result in little endian byte order in dst.
+func xor(dst, src []byte, u uint32) {
+	_, _ = src[3], dst[3] // eliminate bounds checks
+	if unaligned {
+		// The compiler should optimize this code into
+		// 32-bit unaligned little endian loads and stores.
+		// TODO: delete once the compiler does a reliably
+		// good job with the generic code below.
+		// See issue #25111 for more details.
+		v := uint32(src[0])
+		v |= uint32(src[1]) << 8
+		v |= uint32(src[2]) << 16
+		v |= uint32(src[3]) << 24
+		v ^= u
+		dst[0] = byte(v)
+		dst[1] = byte(v >> 8)
+		dst[2] = byte(v >> 16)
+		dst[3] = byte(v >> 24)
+	} else {
+		dst[0] = src[0] ^ byte(u)
+		dst[1] = src[1] ^ byte(u>>8)
+		dst[2] = src[2] ^ byte(u>>16)
+		dst[3] = src[3] ^ byte(u>>24)
+	}
+}
diff --git a/libgo/go/golang_org/x/crypto/poly1305/poly1305.go b/libgo/go/golang_org/x/crypto/poly1305/poly1305.go
index 4a5f826f7a6..f562fa5712b 100644
--- a/libgo/go/golang_org/x/crypto/poly1305/poly1305.go
+++ b/libgo/go/golang_org/x/crypto/poly1305/poly1305.go
@@ -3,7 +3,8 @@
 // license that can be found in the LICENSE file.
 
 /*
-Package poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf.
+Package poly1305 implements Poly1305 one-time message authentication code as
+specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
 
 Poly1305 is a fast, one-time authentication function. It is infeasible for an
 attacker to generate an authenticator for a message without the key. However, a
diff --git a/libgo/go/golang_org/x/crypto/poly1305/poly1305_test.go b/libgo/go/golang_org/x/crypto/poly1305/poly1305_test.go
index 017027fe6e5..256bdbba2f4 100644
--- a/libgo/go/golang_org/x/crypto/poly1305/poly1305_test.go
+++ b/libgo/go/golang_org/x/crypto/poly1305/poly1305_test.go
@@ -5,7 +5,6 @@
 package poly1305
 
 import (
-	"bytes"
 	"encoding/hex"
 	"flag"
 	"testing"
@@ -14,80 +13,51 @@ import (
 
 var stressFlag = flag.Bool("stress", false, "run slow stress tests")
 
-var testData = []struct {
-	in, k, correct []byte
-}{
-	{
-		[]byte("Hello world!"),
-		[]byte("this is 32-byte key for Poly1305"),
-		[]byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0},
-	},
-	{
-		make([]byte, 32),
-		[]byte("this is 32-byte key for Poly1305"),
-		[]byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07},
-	},
-	{
-		make([]byte, 2007),
-		[]byte("this is 32-byte key for Poly1305"),
-		[]byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa},
-	},
-	{
-		make([]byte, 2007),
-		make([]byte, 32),
-		make([]byte, 16),
-	},
-	{
-		// This test triggers an edge-case. See https://go-review.googlesource.com/#/c/30101/.
-		[]byte{0x81, 0xd8, 0xb2, 0xe4, 0x6a, 0x25, 0x21, 0x3b, 0x58, 0xfe, 0xe4, 0x21, 0x3a, 0x2a, 0x28, 0xe9, 0x21, 0xc1, 0x2a, 0x96, 0x32, 0x51, 0x6d, 0x3b, 0x73, 0x27, 0x27, 0x27, 0xbe, 0xcf, 0x21, 0x29},
-		[]byte{0x3b, 0x3a, 0x29, 0xe9, 0x3b, 0x21, 0x3a, 0x5c, 0x5c, 0x3b, 0x3b, 0x05, 0x3a, 0x3a, 0x8c, 0x0d},
-		[]byte{0x6d, 0xc1, 0x8b, 0x8c, 0x34, 0x4c, 0xd7, 0x99, 0x27, 0x11, 0x8b, 0xbe, 0x84, 0xb7, 0xf3, 0x14},
-	},
-	{
-		// This test generates a result of (2^130-1) % (2^130-5).
-		[]byte{
-			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		},
-		[]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},
-		[]byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
-	},
-	{
-		// This test generates a result of (2^130-6) % (2^130-5).
-		[]byte{
-			0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		},
-		[]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},
-		[]byte{0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-	},
-	{
-		// This test generates a result of (2^130-5) % (2^130-5).
-		[]byte{
-			0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-		},
-		[]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},
-		[]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
-	},
+type test struct {
+	in  string
+	key string
+	tag string
 }
 
-func testSum(t *testing.T, unaligned bool) {
-	var out [16]byte
-	var key [32]byte
+func (t *test) Input() []byte {
+	in, err := hex.DecodeString(t.in)
+	if err != nil {
+		panic(err)
+	}
+	return in
+}
 
+func (t *test) Key() [32]byte {
+	buf, err := hex.DecodeString(t.key)
+	if err != nil {
+		panic(err)
+	}
+	var key [32]byte
+	copy(key[:], buf[:32])
+	return key
+}
+
+func (t *test) Tag() [16]byte {
+	buf, err := hex.DecodeString(t.tag)
+	if err != nil {
+		panic(err)
+	}
+	var tag [16]byte
+	copy(tag[:], buf[:16])
+	return tag
+}
+
+func testSum(t *testing.T, unaligned bool, sumImpl func(tag *[TagSize]byte, msg []byte, key *[32]byte)) {
+	var tag [16]byte
 	for i, v := range testData {
-		in := v.in
+		in := v.Input()
 		if unaligned {
 			in = unalignBytes(in)
 		}
-		copy(key[:], v.k)
-		Sum(&out, in, &key)
-		if !bytes.Equal(out[:], v.correct) {
-			t.Errorf("%d: expected %x, got %x", i, v.correct, out[:])
+		key := v.Key()
+		sumImpl(&tag, in, &key)
+		if tag != v.Tag() {
+			t.Errorf("%d: expected %x, got %x", i, v.Tag(), tag[:])
 		}
 	}
 }
@@ -125,8 +95,10 @@ func TestBurnin(t *testing.T) {
 	}
 }
 
-func TestSum(t *testing.T)          { testSum(t, false) }
-func TestSumUnaligned(t *testing.T) { testSum(t, true) }
+func TestSum(t *testing.T)                 { testSum(t, false, Sum) }
+func TestSumUnaligned(t *testing.T)        { testSum(t, true, Sum) }
+func TestSumGeneric(t *testing.T)          { testSum(t, false, sumGeneric) }
+func TestSumGenericUnaligned(t *testing.T) { testSum(t, true, sumGeneric) }
 
 func benchmark(b *testing.B, size int, unaligned bool) {
 	var out [16]byte
@@ -146,6 +118,7 @@ func Benchmark64(b *testing.B)          { benchmark(b, 64, false) }
 func Benchmark1K(b *testing.B)          { benchmark(b, 1024, false) }
 func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) }
 func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) }
+func Benchmark2M(b *testing.B)          { benchmark(b, 2097152, true) }
 
 func unalignBytes(in []byte) []byte {
 	out := make([]byte, len(in)+1)
diff --git a/libgo/go/golang_org/x/crypto/poly1305/sum_noasm.go b/libgo/go/golang_org/x/crypto/poly1305/sum_noasm.go
new file mode 100644
index 00000000000..751eec52743
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/poly1305/sum_noasm.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.
+
+// +build s390x,!go1.11 !arm,!amd64,!s390x gccgo appengine nacl
+
+package poly1305
+
+// Sum generates an authenticator for msg using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
+	sumGeneric(out, msg, key)
+}
diff --git a/libgo/go/golang_org/x/crypto/poly1305/sum_ref.go b/libgo/go/golang_org/x/crypto/poly1305/sum_ref.go
index b2805a5ca17..c4d59bd0987 100644
--- a/libgo/go/golang_org/x/crypto/poly1305/sum_ref.go
+++ b/libgo/go/golang_org/x/crypto/poly1305/sum_ref.go
@@ -2,16 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !amd64,!arm gccgo appengine nacl
-
 package poly1305
 
 import "encoding/binary"
 
-// Sum generates an authenticator for msg using a one-time key and puts the
-// 16-byte result into out. Authenticating two different messages with the same
-// key allows an attacker to forge messages at will.
-func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
+// sumGeneric generates an authenticator for msg using a one-time key and
+// puts the 16-byte result into out. This is the generic implementation of
+// Sum and should be called if no assembly implementation is available.
+func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) {
 	var (
 		h0, h1, h2, h3, h4 uint32 // the hash accumulators
 		r0, r1, r2, r3, r4 uint64 // the r part of the key
diff --git a/libgo/go/golang_org/x/crypto/poly1305/sum_s390x.go b/libgo/go/golang_org/x/crypto/poly1305/sum_s390x.go
new file mode 100644
index 00000000000..7a266cece46
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/poly1305/sum_s390x.go
@@ -0,0 +1,49 @@
+// 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 s390x,go1.11,!gccgo,!appengine
+
+package poly1305
+
+// hasVectorFacility reports whether the machine supports
+// the vector facility (vx).
+func hasVectorFacility() bool
+
+// hasVMSLFacility reports whether the machine supports
+// Vector Multiply Sum Logical (VMSL).
+func hasVMSLFacility() bool
+
+var hasVX = hasVectorFacility()
+var hasVMSL = hasVMSLFacility()
+
+// poly1305vx is an assembly implementation of Poly1305 that uses vector
+// instructions. It must only be called if the vector facility (vx) is
+// available.
+//go:noescape
+func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
+
+// poly1305vmsl is an assembly implementation of Poly1305 that uses vector
+// instructions, including VMSL. It must only be called if the vector facility (vx) is
+// available and if VMSL is supported.
+//go:noescape
+func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
+
+// Sum generates an authenticator for m using a one-time key and puts the
+// 16-byte result into out. Authenticating two different messages with the same
+// key allows an attacker to forge messages at will.
+func Sum(out *[16]byte, m []byte, key *[32]byte) {
+	if hasVX {
+		var mPtr *byte
+		if len(m) > 0 {
+			mPtr = &m[0]
+		}
+		if hasVMSL && len(m) > 256 {
+			poly1305vmsl(out, mPtr, uint64(len(m)), key)
+		} else {
+			poly1305vx(out, mPtr, uint64(len(m)), key)
+		}
+	} else {
+		sumGeneric(out, m, key)
+	}
+}
diff --git a/libgo/go/golang_org/x/crypto/poly1305/vectors_test.go b/libgo/go/golang_org/x/crypto/poly1305/vectors_test.go
new file mode 100644
index 00000000000..18d7ff8e85f
--- /dev/null
+++ b/libgo/go/golang_org/x/crypto/poly1305/vectors_test.go
@@ -0,0 +1,2943 @@
+// 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 poly1305
+
+var testData = [...]test{
+	// edge cases
+	{
+		// see https://go-review.googlesource.com/#/c/30101/
+		key: "3b3a29e93b213a5c5c3b3b053a3a8c0d00000000000000000000000000000000",
+		tag: "6dc18b8c344cd79927118bbe84b7f314",
+		in:  "81d8b2e46a25213b58fee4213a2a28e921c12a9632516d3b73272727becf2129",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "04000000000000000000000000000000", // (2¹³⁰-1) % (2¹³⁰-5)
+		in: "ffffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "faffffffffffffffffffffffffffffff", // (2¹³⁰-6) % (2¹³⁰-5)
+		in: "faffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "00000000000000000000000000000000", // (2¹³⁰-5) % (2¹³⁰-5)
+		in: "fbffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "f9ffffffffffffffffffffffffffffff", // (2*(2¹³⁰-6)) % (2¹³⁰-5)
+		in: "faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "00000000000000000000000000000000", // (2*(2¹³⁰-5)) % (2¹³⁰-5)
+		in: "fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "f8ffffffffffffffffffffffffffffff", // (3*(2¹³⁰-6)) % (2¹³⁰-5)
+		in: "faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "00000000000000000000000000000000", // (3*(2¹³⁰-5)) % (2¹³⁰-5)
+		in: "fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "f7ffffffffffffffffffffffffffffff", // (4*(2¹³⁰-6)) % (2¹³⁰-5)
+		in: "faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "00000000000000000000000000000000", // (4*(2¹³⁰-5)) % (2¹³⁰-5)
+		in: "fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "f3ffffffffffffffffffffffffffffff", // (8*(2¹³⁰-6)) % (2¹³⁰-5)
+		in: "faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "00000000000000000000000000000000", // (8*(2¹³⁰-5)) % (2¹³⁰-5)
+		in: "fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "ebffffffffffffffffffffffffffffff", // (16*(2¹³⁰-6)) % (2¹³⁰-5)
+		in: "faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"faffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	{
+		key: "0100000000000000000000000000000000000000000000000000000000000000",
+		tag: "00000000000000000000000000000000", // (16*(2¹³⁰-5)) % (2¹³⁰-5)
+		in: "fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"fbffffffffffffffffffffffffffffff" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000" +
+			"00000000000000000000000000000000",
+	},
+	// original smoke tests
+	{
+		key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
+		tag: "a6f745008f81c916a20dcc74eef2b2f0",
+		in:  "48656c6c6f20776f726c6421",
+	},
+	{
+		key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
+		tag: "49ec78090e481ec6c26b33b91ccc0307",
+		in:  "0000000000000000000000000000000000000000000000000000000000000000",
+	},
+	{
+		key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
+		tag: "da84bcab02676c38cdb015604274c2aa",
+		in: "000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000",
+	},
+	{
+		key: "0000000000000000000000000000000000000000000000000000000000000000",
+		tag: "00000000000000000000000000000000",
+		in: "000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000000000" +
+			"000000000000000000000000000000000000000000000000000000",
+	},
+	// randomly generated
+	{
+		key: "52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649",
+		tag: "9566c74d10037c4d7bbb0407d1e2c649",
+		in:  "",
+	},
+	{
+		key: "81855ad8681d0d86d1e91e00167939cb6694d2c422acd208a0072939487f6999",
+		tag: "eaa270caaa12faa39b797374a4b8a420",
+		in:  "eb",
+	},
+	{
+		key: "9d18a44784045d87f3c67cf22746e995af5a25367951baa2ff6cd471c483f15f",
+		tag: "dbea66e1da48a8f822887c6162c2acf1",
+		in:  "b90b",
+	},
+	{
+		key: "adb37c5821b6d95526a41a9504680b4e7c8b763a1b1d49d4955c848621632525",
+		tag: "6ac09aaa88c32ee95a7198376f16abdb",
+		in:  "3fec73",
+	},
+	{
+		key: "8dd7a9e28bf921119c160f0702448615bbda08313f6a8eb668d20bf505987592",
+		tag: "b1443487f97fe340b04a74719ed4de68",
+		in:  "1e668a5b",
+	},
+	{
+		key: "df2c7fc4844592d2572bcd0668d2d6c52f5054e2d0836bf84c7174cb7476364c",
+		tag: "7463be0f9d99a5348039e4afcbf4019c",
+		in:  "c3dbd968b0",
+	},
+	{
+		key: "f7172ed85794bb358b0c3b525da1786f9fff094279db1944ebd7a19d0f7bbacb",
+		tag: "2edaee3bcf303fd05609e131716f8157",
+		in:  "e0255aa5b7d4",
+	},
+	{
+		key: "4bec40f84c892b9bffd43629b0223beea5f4f74391f445d15afd4294040374f6",
+		tag: "965f18767420c1d94a4ef657e8d15e1e",
+		in:  "924b98cbf8713f",
+	},
+	{
+		key: "8d962d7c8d019192c24224e2cafccae3a61fb586b14323a6bc8f9e7df1d92933",
+		tag: "2bf4a33287dd6d87e1ed4282f7342b6a",
+		in:  "3ff993933bea6f5b",
+	},
+	{
+		key: "3af6de0374366c4719e43a1b067d89bc7f01f1f573981659a44ff17a4c7215a3",
+		tag: "c5e987b60373a48893c5af30acf2471f",
+		in:  "b539eb1e5849c6077d",
+	},
+	{
+		key: "bb5722f5717a289a266f97647981998ebea89c0b4b373970115e82ed6f4125c8",
+		tag: "19f0f640b309d168ea1b480e6a4faee5",
+		in:  "fa7311e4d7defa922daa",
+	},
+	{
+		key: "e7786667f7e936cd4f24abf7df866baa56038367ad6145de1ee8f4a8b0993ebd",
+		tag: "de75e5565d97834b9fa84ad568d31359",
+		in:  "f8883a0ad8be9c3978b048",
+	},
+	{
+		key: "83e56a156a8de563afa467d49dec6a40e9a1d007f033c2823061bdd0eaa59f8e",
+		tag: "de184a5a9b826aa203c5c017986d6690",
+		in:  "4da6430105220d0b29688b73",
+	},
+	{
+		key: "4b8ea0f3ca9936e8461f10d77c96ea80a7a665f606f6a63b7f3dfd2567c18979",
+		tag: "7478f18d9684905aa5d1a34ee67e4c84",
+		in:  "e4d60f26686d9bf2fb26c901ff",
+	},
+	{
+		key: "354cde1607ee294b39f32b7c7822ba64f84ab43ca0c6e6b91c1fd3be89904341",
+		tag: "3b2008a9c52b5308f5538b789ab5506f",
+		in:  "79d3af4491a369012db92d184fc3",
+	},
+	{
+		key: "9d1734ff5716428953bb6865fcf92b0c3a17c9028be9914eb7649c6c93478009",
+		tag: "71c8e76a67a505b7370b562ba15ba032",
+		in:  "79d1830356f2a54c3deab2a4b4475d",
+	},
+	{
+		key: "63afbe8fb56987c77f5818526f1814be823350eab13935f31d84484517e924ae",
+		tag: "1dc895f74f866bdb3edf6c4430829c1c",
+		in:  "f78ae151c00755925836b7075885650c",
+	},
+	{
+		key: "30ec29a3703934bf50a28da102975deda77e758579ea3dfe4136abf752b3b827",
+		tag: "afca2b3ba7b0e1a928001966883e9b16",
+		in: "1d03e944b3c9db366b75045f8efd69d22ae5411947cb553d7694267aef4e" +
+			"bcea406b32d6108bd68584f57e37caac6e33feaa3263a399437024ba9c9b" +
+			"14678a274f01a910ae295f6efbfe5f5abf44ccde263b5606633e2bf0006f" +
+			"28295d7d39069f01a239c4365854c3af7f6b41d631f92b9a8d12f4125732" +
+			"5fff332f7576b0620556304a3e3eae14c28d0cea39d2901a52720da85ca1" +
+			"e4b38eaf3f",
+	},
+	{
+		key: "44c6c6ef8362f2f54fc00e09d6fc25640854c15dfcacaa8a2cecce5a3aba53ab",
+		tag: "6f2a09aa76c9b76774e31ec02dcf7991",
+		in: "705b18db94b4d338a5143e63408d8724b0cf3fae17a3f79be1072fb63c35" +
+			"d6042c4160f38ee9e2a9f3fb4ffb0019b454d522b5ffa17604193fb89667" +
+			"10a7960732ca52cf53c3f520c889b79bf504cfb57c7601232d589baccea9" +
+			"d6e263e25c27741d3f6c62cbbb15d9afbcbf7f7da41ab0408e3969c2e2cd" +
+			"cf233438bf1774ace7709a4f091e9a83fdeae0ec55eb233a9b5394cb3c78" +
+			"56b546d313c8a3b4c1c0e05447f4ba370eb36dbcfdec90b302dcdc3b9ef5" +
+			"22e2a6f1ed0afec1f8e20faabedf6b162e717d3a748a58677a0c56348f89" +
+			"21a266b11d0f334c62fe52ba53af19779cb2948b6570ffa0b773963c130a" +
+			"d797ddea",
+	},
+	{
+		key: "fe4e3ad29b5125210f0ef1c314090f07c79a6f571c246f3e9ac0b7413ef110bd",
+		tag: "27381e3fc2a356103fb796f107d826e7",
+		in: "58b00ce73bff706f7ff4b6f44090a32711f3208e4e4b89cb5165ce64002c" +
+			"bd9c2887aa113df2468928d5a23b9ca740f80c9382d9c6034ad2960c7965" +
+			"03e1ce221725f50caf1fbfe831b10b7bf5b15c47a53dbf8e7dcafc9e1386" +
+			"47a4b44ed4bce964ed47f74aa594468ced323cb76f0d3fac476c9fb03fc9" +
+			"228fbae88fd580663a0454b68312207f0a3b584c62316492b49753b5d502" +
+			"7ce15a4f0a58250d8fb50e77f2bf4f0152e5d49435807f9d4b97be6fb779" +
+			"70466a5626fe33408cf9e88e2c797408a32d29416baf206a329cfffd4a75" +
+			"e498320982c85aad70384859c05a4b13a1d5b2f5bfef5a6ed92da482caa9" +
+			"568e5b6fe9d8a9ddd9eb09277b92cef9046efa18500944cbe800a0b1527e" +
+			"a6",
+	},
+	{
+		key: "4729a861d2f6497a3235c37f4192779ec1d96b3b1c5424fce0b727b03072e641",
+		tag: "0173965669fb9de88d38a827a0271271",
+		in: "5a761f03abaa40abc9448fddeb2191d945c04767af847afd0edb5d8857b7" +
+			"99acb18e4affabe3037ffe7fa68aa8af5e39cc416e734d373c5ebebc9cdc" +
+			"c595bcce3c7bd3d8df93fab7e125ddebafe65a31bd5d41e2d2ce9c2b1789" +
+			"2f0fea1931a290220777a93143dfdcbfa68406e877073ff08834e197a403" +
+			"4aa48afa3f85b8a62708caebbac880b5b89b93da53810164402104e648b6" +
+			"226a1b78021851f5d9ac0f313a89ddfc454c5f8f72ac89b38b19f53784c1" +
+			"9e9beac03c875a27db029de37ae37a42318813487685929359ca8c5eb94e" +
+			"152dc1af42ea3d1676c1bdd19ab8e2925c6daee4de5ef9f9dcf08dfcbd02" +
+			"b80809398585928a0f7de50be1a6dc1d5768e8537988fddce562e9b948c9" +
+			"18bba3e933e5c400cde5e60c5ead6fc7ae77ba1d259b188a4b21c86fbc23" +
+			"d728b45347eada650af24c56d0800a8691332088a805bd55c446e25eb075" +
+			"90bafcccbec6177536401d9a2b7f512b54bfc9d00532adf5aaa7c3a96bc5" +
+			"9b489f77d9042c5bce26b163defde5ee6a0fbb3e9346cef81f0ae9515ef3" +
+			"0fa47a364e75aea9e111d596e685a591121966e031650d510354aa845580" +
+			"ff560760fd36514ca197c875f1d02d9216eba7627e2398322eb5cf43d72b" +
+			"d2e5b887d4630fb8d4747ead6eb82acd1c5b078143ee26a586ad23139d50" +
+			"41723470bf24a865837c",
+	},
+	{
+		key: "9123461c41f5ff99aa99ce24eb4d788576e3336e65491622558fdf297b9fa007",
+		tag: "1eb0cdad9237905250d30a24fe172a34",
+		in: "864bafd7cd4ca1b2fb5766ab431a032b72b9a7e937ed648d0801f29055d3" +
+			"090d2463718254f9442483c7b98b938045da519843854b0ed3f7ba951a49" +
+			"3f321f0966603022c1dfc579b99ed9d20d573ad53171c8fef7f1f4e4613b" +
+			"b365b2ebb44f0ffb6907136385cdc838f0bdd4c812f042577410aca008c2" +
+			"afbc4c79c62572e20f8ed94ee62b4de7aa1cc84c887e1f7c31e927dfe52a" +
+			"5f8f46627eb5d3a4fe16fafce23623e196c9dfff7fbaff4ffe94f4589733" +
+			"e563e19d3045aad3e226488ac02cca4291aed169dce5039d6ab00e40f67a" +
+			"ab29332de1448b35507c7c8a09c4db07105dc31003620405da3b2169f5a9" +
+			"10c9d0096e5e3ef1b570680746acd0cc7760331b663138d6d342b051b5df" +
+			"410637cf7aee9b0c8c10a8f9980630f34ce001c0ab7ac65e502d39b216cb" +
+			"c50e73a32eaf936401e2506bd8b82c30d346bc4b2fa319f245a8657ec122" +
+			"eaf4ad5425c249ee160e17b95541c2aee5df820ac85de3f8e784870fd87a" +
+			"36cc0d163833df636613a9cc947437b6592835b9f6f4f8c0e70dbeebae7b" +
+			"14cdb9bc41033aa5baf40d45e24d72eac4a28e3ca030c9937ab8409a7cbf" +
+			"05ae21f97425254543d94d115900b90ae703b97d9856d2441d14ba49a677" +
+			"de8b18cb454b99ddd9daa7ccbb7500dae4e2e5df8cf3859ebddada6745fb" +
+			"a6a04c5c37c7ca35036f11732ce8bc27b48868611fc73c82a491bfabd7a1" +
+			"9df50fdc78a55dbbc2fd37f9296566557fab885b039f30e706f0cd5961e1" +
+			"9b642221db44a69497b8ad99408fe1e037c68bf7c5e5de1d2c68192348ec" +
+			"1189fb2e36973cef09ff14be23922801f6eaee41409158b45f2dec82d17c" +
+			"aaba160cd6",
+	},
+	{
+		key: "40ff73495fe4a05ce1202ca7287ed3235b95e69f571fa5e656aaa51fae1ebdd7",
+		tag: "2e619d8ea81b77484e4fddeb29844e4b",
+		in: "aa6269c2ec7f4057b33593bc84888c970fd528d4a99a1eab9d2420134537" +
+			"cd6d02282e0981e140232a4a87383a21d1845c408ad757043813032a0bd5" +
+			"a30dcca6e3aa2df04715d879279a96879a4f3690ac2025a60c7db15e0501" +
+			"ebc34b734355fe4a059bd3899d920e95f1c46d432f9b08e64d7f9b38965d" +
+			"5a77a7ac183c3833e1a3425ead69d4f975012fd1a49ed832f69e6e9c63b4" +
+			"53ec049c9e7a5cf944232d10353f64434abae060f6506ad3fdb1f4415b0a" +
+			"f9ce8c208bc20ee526741539fa3203c77ecba410fd6718f227e0b430f9bc" +
+			"b049a3d38540dc222969120ce80f2007cd42a708a721aa29987b45d4e428" +
+			"811984ecad349cc35dd93515cefe0b002cee5e71c47935e281ebfc4b8b65" +
+			"2b69ccb092e55a20f1b9f97d046296124621928739a86671cc180152b953" +
+			"e3bf9d19f825c3dd54ae1688e49efb5efe65dcdad34bc860010e7c8c997c" +
+			"d5f9e320ca7d39d4ba801a175b1c76f057832f3f36d7d893e216e4c7bbdb" +
+			"548d0ba48449330027368b34f9c69776b4591532da1c5be68ef4eebe8cb8" +
+			"fa7dc5483fb70c2c896334cb1f9cb5dfe044fa086197ff5dfd02f2ba3884" +
+			"c53dd718c8560da743a8e9d4aeae20ccef002d82ca352592b8d8f2a8df3b" +
+			"0c35f15b9b370dca80d4ca8e9a133eb52094f2dd5c08731f52315d828846" +
+			"e37df68fd10658b480f2ac84233633957e688e924ffe3713b52c76fd8a56" +
+			"da8bb07daa8eb4eb8f7334f99256e2766a4109150eed424f0f743543cdea" +
+			"66e5baaa03edc918e8305bb19fc0c6b4ddb4aa3886cb5090940fc6d4cabe" +
+			"2153809e4ed60a0e2af07f1b2a6bb5a6017a578a27cbdc20a1759f76b088" +
+			"9a83ce25ce3ca91a4eb5c2f8580819da04d02c41770c01746de44f3db6e3" +
+			"402e7873db7635516e87b33e4b412ba3df68544920f5ea27ec097710954f" +
+			"42158bdba66d4814c064b4112538676095467c89ba98e6a543758d7093a4" +
+			"94df",
+	},
+	{
+		key: "5cc36d09c7a6472a41f29c380a987b1ecdcf84765f4e5d3ceefc1c02181f570f",
+		tag: "0d57b8cbea8090df0541354673dcb4e0",
+		in: "44fcd629f08dc1ef53c9ae0d8869fe67fdc7a2c67b425f13c5be8d9f630c" +
+			"1d063c02fd75cf64c1aec9d2e2ef6e6431d5f5ad0489078dc61f46494dcc" +
+			"f403dad7f094170d2c3e29c198b0f341e284c4be8fa60c1a478d6bd55dd2" +
+			"c04dad86d2053d5d25b014e3d8b64322cdcb5004faa46cfa2d6ad2ff933b" +
+			"c3bd9a5a74660af3d048a9a43634c0250427d9a6219197a3f3633f841753" +
+			"ba7c27f3619f387b6b1a6cb9c1dc227674aa020724d137da2cb87b1615d5" +
+			"12974fa4747dd1e17d02c9462a44fec150ca3a8f99cc1e4953365e429956" +
+			"5e108535b1f62e1d4ba18e17a52164418bfd1a933f7fb3a126c860830a87" +
+			"293d9271da736e4398c1e37fb75c4bf02786e1faf4b610cd1377fbb9ae18" +
+			"0655a0abefbad700c09473469f1eca5a66d53fa3dc7cd3e7c3b0411d7e14" +
+			"5f96eb9654ab94913dda503a50f9e773842f4d2a5faa60869bf365830511" +
+			"f2ededd03e0a73000edb60c9a29a5f5e194cf3b5667a694690384599d116" +
+			"f8d2fd93b2aed55b7d44b5b054f3f38e788e4fdf36e591568c41d1052cad" +
+			"0fcb68ca4c4bf5090d57df9db6f0d91dd8b11b804f331adb7efb087a5604" +
+			"e9e22b4d54db40bcbc6e272ff5eaddfc1471459e59f0554c58251342134a" +
+			"8daaef1498069ba581ef1da2510be92843487a4eb8111c79a6f0195fc38a" +
+			"d6aee93c1df2b5897eaa38ad8f47ab2fe0e3aa3e6accbfd4c16d46843318" +
+			"5fc61c861b96ca65e34d31f24d6f56ee85092314a4d7656205c15322f1c9" +
+			"7613c079eae292ba966e10d1e700164e518b243f424c46f9ea63db1c2c34" +
+			"b512c403c128ee19030a6226517b805a072512a5e4cd274b7fd1fa23f830" +
+			"058208ff1a063b41039c74036b5b3da8b1a0b93135a710352da0f6c31203" +
+			"a09d1f2329651bb3ab3984ab591f2247e71cd44835e7a1a1b66d8595f7ae" +
+			"f9bf39d1417d2d31ea3599d405ff4b5999a86f52f3259b452909b57937d8" +
+			"5364d6c23deb4f14e0d9fcee9184df5994fdc11f045c025c8d561adb0e7d" +
+			"fd4748fd4b20f84e53322471a410cdb3fd88e48b2e7eb7ae5dae994cb5ea" +
+			"e3eaf21cf9005db560d6d22e4d9b97d7e9e488751afcd72aa176c0fcde93" +
+			"16f676fd527d9c42105b851639f09ea70533d26fc60cbeb4b76ed554fc99" +
+			"177620b28ca6f56a716f8cb384",
+	},
+	{
+		key: "811c3e356e7c793acf114c624dc86ace38e67bff2a60e5b2a6c20723c1b9f003",
+		tag: "c6e59044cefc43ee681c3eed872d02b3",
+		in: "e115b304c023792448794546a2474f04294d7a616215e5dd6c40a65bb6ed" +
+			"b508c3680b14c176c327fdfb1ee21962c0006b7deb4e5de87db21989d13c" +
+			"3ab0462d5d2a52ef4ca0d366ae06a314f50e3a21d9247f814037798cc5e1" +
+			"0a63de027477decdeb8a8e0c279299272490106ddf8683126f60d35772c6" +
+			"dfc744b0adbfd5dcf118c4f2b06cfaf077881d733a5e643b7c46976647d1" +
+			"c1d3f8f6237c6218fa86fb47080b1f7966137667bd6661660c43b75b6339" +
+			"0b514bbe491aa46b524bde1c5b7456255fb214c3f74907b7ce1cba94210b" +
+			"78b5e68f049fcb002b96a5d38d59df6e977d587abb42d0972d5f3ffc898b" +
+			"3cbec26f104255761aee1b8a232d703585dd276ee1f43c8cd7e92a993eb1" +
+			"5107d02f59ba75f8dd1442ee37786ddb902deb88dd0ebdbf229fb25a9dca" +
+			"86d0ce46a278a45f5517bff2c049cc959a227dcdd3aca677e96ce84390e9" +
+			"b9a28e0988777331847a59f1225b027a66c1421422683dd6081af95e16f2" +
+			"48ab03da494112449ce7bdace6c988292f95699bb5e4d9c8d250aa28a6df" +
+			"44c0c265156deb27e9476a0a4af44f34bdf631b4af1146afe34ea988fc95" +
+			"3e71fc21ce60b3962313000fe46d757109281f6e55bc950200d0834ceb5c" +
+			"41553afd12576f3fbb9a8e05883ccc51c9a1269b6d8e9d27123dce5d0bd6" +
+			"db649c6fea06b4e4e9dea8d2d17709dc50ae8aa38231fd409e9580e255fe" +
+			"2bf59e6e1b6e310610ea4881206262be76120d6c97db969e003947f08bad" +
+			"8fa731f149397c47d2c964e84f090e77e19046277e18cd8917c48a776c9d" +
+			"e627b6656203b522c60e97cc61914621c564243913ae643f1c9c9e0ad00a" +
+			"14f66eaa45844229ecc35abb2637317ae5d5e338c68691bea8fa1fd469b7" +
+			"b54d0fccd730c1284ec7e6fccdec800b8fa67e6e55ac574f1e53a65ab976" +
+			"4c218a404184793cc9892308e296b334c85f7097edc16927c2451c4cd7e5" +
+			"3f239aa4f4c83241bde178f692898b1ece2dbcb19a97e64c4710326528f2" +
+			"4b099d0b674bd614fad307d9b9440adab32117f0f15b1450277b00eb366e" +
+			"0260fca84c1d27e50a1116d2ce16c8f5eb212c77c1a84425744ea3195edb" +
+			"b54c970b77e090b644942d43fe8c4546a158bad7620217a40e34b9bb84d1" +
+			"89eff32b20ef3f015714dbb1f150015d6eeb84cbccbd3fffa63bde89",
+	},
+	{
+		key: "f33691f5db2dea41e1e608af3ff39f3a6988dba204ce1b09214475ae0ea864b8",
+		tag: "6e50e70411201378c8d67857d7b631d2",
+		in: "439bc9ea10db4d2b08c7fcf2e8bd89fa9844f8061d462e28f174489e7514" +
+			"0f84e842040141cc59ce38f9551850cfbdfac2d75337d155090d70d0d930" +
+			"04340bdfe60062f17c53f3c9005b9995a0feb49f6bef8eaff80f4feb7ef3" +
+			"f2181733a4b43b6ac43a5130a73a9b3c2cbc93bd296cd5f48c9df022b6c8" +
+			"2bb752bc21e3d8379be31328aa32edc11efc8a4b4b3f370ee8c870cd281d" +
+			"614e6bc2c0a5ca303bc48696a3bd574ee34738de4c4c29910f8feb7557bf" +
+			"ffcfe7428b4703144bd6d7fe5b3f5de748918553df5453b3c6001696f3de" +
+			"0137e454aadf30cedfb6be36b0b908a38409f1a2dc202fc285610765e4c8" +
+			"6414692bf4bde20ed899e97727b7ea1d95d7c621717c560f1d260ab3624e" +
+			"d6168d77c483dd5ce0d234049017795f2e5a7569d7ad323c50a5b1170337" +
+			"4174a9977026c20cd52c10b72f14e0569a684a3dcf2ccbc148fd3db506e2" +
+			"8d24f6c55544cb3980a36e86747adc89ebad78d1630618d113fa445f8625" +
+			"b583cd7be33913c30c419d047cf3baf40fd05219a1fcec717b87a65fa022" +
+			"1a3aa8143062d77588168019454240ae3d37640996f2967810459bc658df" +
+			"e556de4d07263dc3d9158ec242008226d1c6aea7f0846e12ce2d316e80da" +
+			"522343264ec9451ec23aaaa367d640faad4af3d44d6d86544ade34c93518" +
+			"2843f6b4d1c934996778affa9ee962e7dfef5e70d933d4309f0f343e9606" +
+			"1b91b11ac380a9675e17a96099fe411bedc28a298cd78d5496e28fbbd4f5" +
+			"b0a27735d1144348e22be5b75724d8f125e99c4cb4e9c3a1f0b4e9da5146" +
+			"e6afaa33d02fda74bf58a8badee2b634b989c01755afa6ab20ee494c6ae4" +
+			"c2c6f17af6b53b61d2947d83a18eb3b8a1612aad5d3ea7e8e35f325c9168" +
+			"ac490f22cb713ddb61fbd96011c5849ac8e2fcd42db820349bdf9157dcc0" +
+			"0d9f9ed9c099b10c7194d48b623b0df43759734b2a2e5f8a35e7192bf9a0" +
+			"03dcb9d16a54bd84d922f85b6021b28aacc5264fe9e83deb48f18f864cbd" +
+			"367eb163d39c45b0eb907311a2a4b09fb26109088df782ce031b02f3caff" +
+			"d2dbe25b1cbde9f35ba7c47292a4fd49e7def7a28824f3dfda259a86c3de" +
+			"59257c255c712686ee47d128a55c7b9e8c546035eab7e2da420f32ed5c94" +
+			"bc12a34dc68eb99257a7ea03b69d6c760b0681fa24e4ca97b7c377182ab5" +
+			"fee30a278b08c44c988a8f925af2997883111c750d176b432735868208f4" +
+			"0de7137331b544f2d28040a3581d195e82811c945c3f9fde68fc21b36a44" +
+			"e1cfa2d8eb625f3102461539b3f13c660936a5ddb29a0ae791fbf52c2f69" +
+			"7bd334653f3605b362d91cd78569b41dbd09b2a5892440b5097fa08d0b4b" +
+			"291fc5b934585dd8d5adc80d573fdd194b2eae26dfc49f5e51c1f1607d7e" +
+			"87740702f244bf39ca1d52423e0ae84891dfdf4f43ef984c7a5f293a2007" +
+			"a1e00e39c757f064518953f55621f955986f63",
+	},
+	{
+		key: "d115b6ac998a65b48b3dae5977abaf985258d3d1cfe1616cec3d6a77f7a75785",
+		tag: "b431c9318ec2769fc8ee8f5fc3c079c3",
+		in: "7e7eb43839a6d7616b8a7b1fb7144817904342a9bd34167051162941a6b1" +
+			"b85db5e587f76e4a53211755d5ab29c11822d7711a97b3f1ff5b21f2485d" +
+			"9c86241fb56cdd6796245d3112df11ad9a7344db44d09934c4efb280ed65" +
+			"80cfcafb5c97a32993cbbf4917183e0b7bb38f2ce2479c28e1d39f673962" +
+			"17a7010448dfd39a4e7f406c8bd2d804f993bb410fffa4eb57518a531ecf" +
+			"259a8af068230acb826d9ffc20ee0fc43885221a321e3928971bb28615f0" +
+			"d9f099f5b68a80503a910fdba0bc643c60b64837900be38770b6b30c362c" +
+			"4580722b5dbb1b9c8cd02a18fd7b5661d2c4d28aa941c50af6655c826690" +
+			"37312fbf9f1cf4adb0b9400532755011b40e8252bd0e3c7a22efb0ef9122" +
+			"1e04b4aa8316d4a4ffeaa11909d38cc264650e7ca416835ded0953f39e29" +
+			"b01d3a33bba454760fb0a96d9fe50b3e42c95271e57840380d1fd39a375b" +
+			"3e5513a31a4b80a2dad8731d4fd1ced5ff61e1fbe8ff3ff90a277e6b5631" +
+			"f99f046c4c3c66158554f61af2ede73aede97e94b1d1f129aaadf9b53548" +
+			"553cc2304103e245b77701f134d94d2a3658f2b41108c5a519c2c8f450db" +
+			"027824f1c0ab94010589a4139ff521938b4f0c7bf0986585f535b6e292e5" +
+			"b3ded23bf81cec17c8420fe67a449e508864e4cbb7eaf335975668f013e9" +
+			"da70b33bd52a72094a8f03762ea7440ce9fcd10e251837cfc9ccc1a8cc47" +
+			"0c67379f6a32f16cf70ea8c19d1a67779a9b2d2b379665e0e908a88b26e7" +
+			"8c9f94f17acefa6d5feb70a7095e0297c53e091cf98df132a23a5ce5aa72" +
+			"59f1154b92e079f0b6f95d2a38aa5d62a2fd97c12ee7b085e57cc4652863" +
+			"8defacc1e70c3aceab82a9fa04e6aa70f5fbfd19de075bee4e3aac4a87d0" +
+			"ad0226a463a554816f1ebac08f30f4c3a93fa85d79b92f0da06348b4f008" +
+			"880fac2df0f768d8f9d082f5a747afb0f62eb29c89d926de9fc491921474" +
+			"1d8647c67d57ac55f94751389ee466bbd44dbe186f2f38abbc61a0425613" +
+			"e9b6a64e6bcb45a2e2bb783b9103483643d5610a7e2dcdb10b5d78423285" +
+			"506b42a99b00a4fb7b619b4526bb4ec78299dd01ad894fde2f053e18c55b" +
+			"6047f86333f2690c2cb8e87d9834ab8a5e339aa346e4d9952ed62dc083e3" +
+			"b11a823a67f23fec099a033f127ebe8626a89fa1a5a6b3520aa0d215a8e7" +
+			"dea3af37907686c16521739a95d6c532cc259c497bf397fceaea49cd46b9" +
+			"ad5c1b39a36fdd2f0d2225fef1b6ca2bb73fe604646c10ba4c572ab13a26" +
+			"559ededc98f5a34c874cc25621e65ba4852529b5a4e9c1b2bf8e1a8f8ff0" +
+			"5a31095b84696c6381eb9ad37ac0db184fe5fccf3554e514946a33cabe6f" +
+			"4d617b549d28ad1cc4642dac96e0215ee1596481600d3619e8f45e2c9ae1" +
+			"da834d44aca216bba0efef6254503ca90339f2d7ca508b2722d50c08def8" +
+			"a736590fa44855cd9eb9979c743783aa26e633696739f2ae25ff7b72ceb2" +
+			"4dff4455b85bbd675c8cb71ad18386dc58c371bdf37b4b3875b98a9423ff" +
+			"3becfc0d0ba2aacab3ee7683cb3b345095fefcaca5751ca793da63c89428",
+	},
+	{
+		key: "f3717306b9729be998cdb2c9d856306c5ae3d89da2cdcef12f86f6110c98d873",
+		tag: "907dba0f4849c7cf4570b5128b5f31d5",
+		in: "079572187d4559f24d8e48dc366441acf226a4db79e214ec3ee288acc349" +
+			"887e2e377419bcafa377d0151497b52e4d9cf2a02b0fc91ad9516482bdf6" +
+			"eccd1497954b53241bfb0bc5c04cc45045c6251f23a510060fee32721872" +
+			"bbc95cd8d400dff00bcac2ecce6229c7d73d8f85ed5a87afdccf6dedd299" +
+			"2d5c7b5b8090c47c737ded036ff0e9aedf02a2242fd9820be618b9601e73" +
+			"d3ba5d8f1ae9805cfd2306251704bc74e3546997f109f1dfae20c03ff31f" +
+			"17564769aa49f01233c9c4b79f90fa3d1433d18cdc497914046ad77d2792" +
+			"2588a7d0e61d4258d7d80cdab8503e3111ddca22cf7f39c1f80f1e16a68d" +
+			"9e21db8b53dd316dfa4233cb453a39a90101c60efc08514a3057db007e96" +
+			"507745bd4a0764ed8717a250bffb5fd1ea58474bdfb5b869681939693926" +
+			"40d832a3387ed4ac9cdab0d2af8fcb51b86e4d927097f1e79b5af96574ec" +
+			"d59d0dd150a0208978c41de28ad6cadf72a49279cffd6dc281c640f2e294" +
+			"4cde49a13ed390da1dd92e3011ce0f4a0863375a9db3f67fca1e3b8288a0" +
+			"78611161d7cb668ecdb932e1ff3733982c8c460eeeff2bca46c96e8a02cf" +
+			"b55d770940de556373a4dd676e3a0dd66f1280c8cb77a85136b3f003fab4" +
+			"887dad548de7bfe6488ae55e7a71da4097db03900d4b94e776a939530328" +
+			"83492da900b2a6c3e73d7a6f12ee30c9dd06cc34e5a3893976eb1de5864d" +
+			"32e792ac02e68d052d9d0cfc7cfb40b77728422f6c26cf68987c6b40fcfe" +
+			"9d660abc657360eb129de11bd70af5eb8fe350af2c27a6ece2cdf81b94c8" +
+			"0e68e8c51106497cfa5171236efe2d71d76b5dff3352af9b407dc5aab60f" +
+			"46b5683646f5b28732b7c750d351a08a507243d8e437cc4bef13a3edaa20" +
+			"5fc4e9968b4e563fa0dc965ba20b8e48bc188a321b16d3213bed69647512" +
+			"7a20afc1a3680ef261df6d37b017dee05cfc3a42e4130216e5540cf715c4" +
+			"e638d7d615c50bef576eeb19b3b15b2c2b454dfcef2b18161a143ddf52fc" +
+			"8e88fa71cbe34c92cd4b5a0adc81e5c33e11d2721bc1b95a9e693ac3cabc" +
+			"490889a8a42bf7e22375b679e8598c8faef22a006ed2da8ab1c08aaed2f5" +
+			"6d6f26649036335c0881bfec1e3a5346335c3b3707ee92173f1a7a3305c2" +
+			"933f78e995da8f1df64daf12b81ce23c8813c27fd4551103dc33561c2e80" +
+			"45b6b6770fa03498fd359a104884699d628020173edbcc4398b977e456e4" +
+			"885964840466176a490e7c513ba5d66090277c1ab1632a995a54f555a452" +
+			"1170a000507865b6650730aa6d6050a55959102836fff3d37e4773340e59" +
+			"2e56951ff9652519de4421d9c5b63edbeb30a3852a1ea110a9a29721aee3" +
+			"23d5a306de1624cecc87badc47aa87f489635d2fb60bff62ba67f5257999" +
+			"6af0a1f1a6fbcd8704e119196fcc289a6db6a4170a2cae31a1d30744b702" +
+			"2536d1526d41659c2dcc8b39c26aecfc0f8a707136d81b2827a158fd7386" +
+			"a537514471c213a8c859016748e0264cf3fbde10f40c620840ec4df99432" +
+			"e2b9e1e368e33f126ec40c572e841c2618d49d4eb098b9533b1f4ae00b46" +
+			"8d15de8c8ab6d0b650e599576f2bd90a124c9c6a0f911fd1bd8253bac272" +
+			"942cbdf8864f3747ff7f09d8a5a9d8599be7ee1744e5f1faf3e526cd2a06" +
+			"b157527272af9d38565957c9ce663c295766c0e0e464971c6282b70d4c0c" +
+			"1fb3b69856b34c089ad2b2c745f5a033cee1429c5b855581ee285278893c" +
+			"43a5968d9c28384b7abe8d072ba69089c938685cb1eab461f05314ad6d06" +
+			"eaa58512f8738bde35b7b15ef359dd2e8753cb1ed6",
+	},
+	{
+		key: "9772c1a4b74cbf53586e5df04369b35f1fdca390565872251bc6844bc81bda88",
+		tag: "68eb7fc459ecc3be819485001ab438dc",
+		in: "e115cc2f33e367cb85c01a914b3a512404ad6a98b5b0c3a211d4bffd5802" +
+			"ee43b3fb07451c74524ec8b4eddbb41ca33dd6e49791875d716a44bec97b" +
+			"7c2d4546616939ffa3b1ab9b8ba1d1a637e7c985cc922606caa0453085e3" +
+			"5f2fe0bd2de129d1d1856ade975a3281a62965927d8bb695e54514e69558" +
+			"89361a2a00a1b24e62bda78d0b71a0d40147016fcdaf1a702331dda8e678" +
+			"d8f476dcc91698da1688c610ec0cb1d9b8fbcd45dfde6d1503ba60a01337" +
+			"ae5b2f5c854a82c3087779babd2e522dd92f4718cd9f8c649ac226745ca2" +
+			"fa1696442764758f67cd926369578ae87612790dc56ed9cda935281a490e" +
+			"5c984950ec7a4e930520d273a69da4ed3a330e532508e26f942961fed0e3" +
+			"efeed52a7b96250d723155aa39a8ae85131c255c32bf406b647de1a37fba" +
+			"dc61e302bb5b70adec4505ee66b3a1d1b7bfe9c58b11e53ad556d56e5807" +
+			"017bb30b71be94e8f86aaf1496e8b8d6db75ec0afbe1cd336c23963c745d" +
+			"7b4ba1787ceb30728f1762b46f6eaad5064c8029d29b86266b87f93142a2" +
+			"74f519f3281d8c1cb43c23eb184ae41f3f625cf624b05a48d73cd7783fdf" +
+			"14954a03ec1a930e9a954424eff030e3f15357de4c19983f484619a0e9e2" +
+			"b67221cf965e9aa8d8926595c793adfe0181050df8b845ce648a66df532f" +
+			"78b10c83ecc86374a4f8abf8edcc303654bafd3dcc7de9c77a0a9d1d98fb" +
+			"121534b47d16f75b55fdc2a5e2e6799f8a2f8000d4292282e56863ae422a" +
+			"5779900ad6881b78946e750d7777f33f2f013a75c19615632c0e40b98338" +
+			"1e9b8d35a26abe30242c45662eebb157e6d7a8a5519de60268ac289b8295" +
+			"5d4feb47b9eef6da65031c6f52c2c4f5baa36fce3618b6a331f1e8bdd621" +
+			"48954fcf0846afeeb0a6cadb495c909a7fe671b021d5b0b4669961052187" +
+			"d01b67d44218471bfb04c1a3d82bf7b776208013fc8adabaefb11719f7a7" +
+			"e6cb0b92d4cc39b403ceb56bd806cbdcc9ee75362ab4aaeb760e170fdc6a" +
+			"23c038d45f465d8ec8519af8b0aad2eb5fae2972c603ed35ff8e46644803" +
+			"fc042ff8044540280766e35d8aaddcaa81e7c0c7eba28674f710492924c6" +
+			"1743da4d241e12b0c519910d4e31de332c2672ea77c9a3d5c60cd78a35d7" +
+			"924fda105b6f0a7cc11523157982418405be0bacf554b6398aeb9a1a3b12" +
+			"fe411c09e9bfb66416a47dd51cbd29abf8fbbd264dd57ba21a388c7e19e8" +
+			"12e66768b2584ad8471bef36245881fc04a22d9900a246668592ca35cfc3" +
+			"a8faf77da494df65f7d5c3daa129b7c98cef57e0826dee394eb927b3d6b3" +
+			"a3c42fa2576dcc6efd1259b6819da9544c82728276b324a36121a519aee5" +
+			"ae850738a44349cdec1220a6a933808aee44ba48ce46ec8fb7d897bd9e6b" +
+			"c4c325a27d1b457eb6be5c1806cd301c5d874d2e863fb0a01cbd3e1f5b0f" +
+			"8e0c771fca0c0b14042a7b0f3ae6264294a82212119b73821dcfbbfd85bb" +
+			"625b6f75e4dc0ee0292ab4f17daf1d507e6c97364260480d406bd43b7d8e" +
+			"8c2f26672a916321b482d5fa7166e282bfeed9b3598c8f8c19d2f8c8b98d" +
+			"f24c2500c8ad41cd6ed3f2835737916d846f1a6406cda1125ed7740fe301" +
+			"d1144559b7c95fa407599ae40a795226513153f86c9b8abe7d8aa6963c99" +
+			"5646ec586cbf20a03a698cc0681b7bd333402d00fa8e15cb32300b5a24ea" +
+			"316c5e1df67de78891846cb9183a4b112c3bcc17bcaa5fecd6c1dbbf6ef8" +
+			"272d9269e7f0ba9f17050a6aa5f11cb28874360396ab647941f2c9a85cb0" +
+			"6a969919b16997b0827af8f909c614545f1ad638ebb23109f6bab6b49b22" +
+			"b2285cabbb998b3e1bf42771b4d4e52330b224e5a1d63169ec85fe1c7dd2" +
+			"46dbafa6138448420f463d547a41c2b26026d4621b854bc7786ab3a0a93a" +
+			"e5390dd840f2454028b7c3bb87680f04f084089bbc8786ee42cf06904d01" +
+			"7e405144d2fae141599e2babe71abfbe7644fb25ec8a8a44a8928ff77a59" +
+			"a3e235de6bd7c7b803cf3cf60435e473e3315f02d7292b1c3f5a19c93646" +
+			"3cc4ccd6b24961083756f86ffa107322c5c7dd8d2e4ca0466f6725e8a35b" +
+			"574f0439f34ca52a393b2f017d2503ba2018fb4a0991fddc1949832d370a" +
+			"27c42e",
+	},
+	{
+		key: "d18a328b63a1d0f34e987682fe6ca3d48b4834b4312a17e99b3d88827b8d2238",
+		tag: "938b43b80cb3935e39b21dd8ba133cf8",
+		in: "bc2b0baf92580ee6c5efe640f2a029a791a3c77bec459be74cbc30931508" +
+			"d9f312c3a0944212831cbe4fc92e8f107f2f750c91bcc09f7624fa9a09b4" +
+			"9b7712cf5d619ea9da100fc23068ae2f4e353047e3956b215884bdb12235" +
+			"3f06b8ee98f36c3212493d61ae9ce151cd0453f3075b18a12d7d73da3de7" +
+			"dc2d98376cfb420069ca8148c511ca6bbae57572394a3c615a6fefb30c5f" +
+			"d727f964b4065ac9ee252bdd2bcae3e70162fe0e8069974e073f0a093d45" +
+			"be52d7de16a8f5f65c548aa6525822ffb00dc642530fedf355f7188ef017" +
+			"56384760c80afb61ad903d10119a7d615ec4fbdc79c490160bdeaf200915" +
+			"e405f2a921a2380c0ab9d2ac1e4fdc8ec4b907368c004458598efac13dc7" +
+			"2751e7faded538e3dc8b16590cac9b7ec294da0ad53e22cb9c05d8ef494f" +
+			"a04f6ab7c843c867fbe3cf1b4eb146d65339b0b03392259f12627a8e98e8" +
+			"0f4896c30b8ecd210acb2365539a872541921dcd8e1e54caf4936dfc7e1f" +
+			"68f3bbce61d325b447a8cce7f0fcad28494f2e47dae46b136594b5dfca7a" +
+			"bdafd6856f91496c05b21079aa55aa8c41628220a2cf0cdd755893375b7b" +
+			"b13d914c9a1d1db4a18f8fa36c55e52d0342352052032fb62d32fcd51cb1" +
+			"ac46f44b06e682db5d96d583cda03b966c650c03ae53542e8da1066b6884" +
+			"4a7e2280c664415e413f270b1fdcfbb40b9daa6131d071ee7eb1553dc5b1" +
+			"a50677971223dc316d2d326d57cbd529c88698facdca425e2d5c6b10d7ae" +
+			"cae28b8890aa44ede9b9193dbe8d1d8aa1fa580ca384b57eadcbefc96dd8" +
+			"bfccbe3b855a96f1fd4913035f817b75954ef1827c7718aab24d353e41cb" +
+			"a73748e14e0c2750d5b6a9752125708cc7ee7a498c7fbadf4186e7f8fa93" +
+			"bfdf281a49400f877621651b8ba87edda5231e80b758564e75139b61b1a9" +
+			"9fb9ec694f928ab1f47c6c4287bd4182d1b2be053380616e98da06f3ef57" +
+			"b570ade17c51da1d602b6ebc5a638ebde30d99bf4f91d0e01557c7dcd8f7" +
+			"9e5120143c935fc699eb5616ccd3cac56b5f8a53ed9e6c47ba896bfefe71" +
+			"2004ad908c12cf6d954b83bec8fb0e641cc261ff8f542b86e62d90e227f2" +
+			"a5bd59c9d390c0dd857f6da2b7624787a0bb31908bae84896890b283da61" +
+			"d8ec4f56eea38b22b438d6374b42243f9c1d94288874e53ab90c554cc1f1" +
+			"d736acde67aff55007fd4b3becc4d0f3ddd96f10dc75255cb0327aa47076" +
+			"2b3a3a656e33c87b02a682658b6cd2a75d9c0462803c9bbffa51441501a0" +
+			"3a2fbb2344aa13d27ffb9e98704ea6720b6a9992e53449688cd74d0648fa" +
+			"e8e776b0ea6bf048b2ec05341e5948cab0af015328b284ae7bd89a5f763c" +
+			"eaf5ca3e647a9f5bff7197e4d357e4359fa5fe30709545453149be510e3b" +
+			"ff86beeba5110c79c0215fbe9ac9339a8ac7d41f7488588ab14ac657aaf7" +
+			"d5c03a353932bbb2b261f0e83f3526c5e8e0c2348a10ab4eed6ecdcf9014" +
+			"7550abcb0a722f257e01d38bad47cdd5a64eef43ef4e741bf50da275720a" +
+			"0aee47adfc5cd2534b911dc269197c3c396820b303f6941e3fd85b5ed21d" +
+			"6d8136745c3eeb9f36b1f226434e334dc94be8a5606079cb7643136aacd2" +
+			"da9c38b2eb7e2b898bd8632003767bf0c87d00a3c2fcee48bbbcdd949af3" +
+			"3455128216709df25879b0ce894ac4f121dfca6b8c7865002b828696641d" +
+			"14ffc59924fbda50866fded0afaea545c8008c564a3a0b023f519a9980ea" +
+			"d541d91d1c07a739fd02286ea5660e473f80494236a68e84ea31aad71348" +
+			"e45055ded69c39941e31d51df257a4d0b0d8f025dbedee093f2b91795bc1" +
+			"533dc472020769a157a187abd6d8d52e1693e2ef56b2212759d0c0120e54" +
+			"c425d0084fdb3925e296dd6cdd8e677043a90674904057d88ebdea5998aa" +
+			"03562a790adecc4399352df43e5179cf8c584d95ef8e4b37295946b1d37f" +
+			"faf4b3b7b98869184e42ea8b304fe1059f180ff83d14a0861ca7c0682c34" +
+			"b48a70df8653bd8d9a26f9489e1271fa44e41b392e648d0e619ecdad2c53" +
+			"952094802eeb70ade4ffe096e3049867de93a824217e31364b18204e9681" +
+			"dd8e84ae2678aad155b238f59dd9bf9ce07e97183a690b2a46a8f3624843" +
+			"5b2f713e7d8dcda4dea1e3c4cf9692dda082322c51f7bb1f63d92aa987ec" +
+			"cf1355a043e21a7b8d60a2b97f18487f6fff4c77df92dbfdc9837540c518" +
+			"9fd9585731bc6e726a34ca21154b0499522c9d1016953dd0fa2eb6a92b6d" +
+			"14d6e3da5c12fabe92bd639e253983fc91041091791643",
+	},
+	{
+		key: "46e8eb27acfdc8f4be622d8741c7bc414464c149e21da97ab4afbf3e07b98b0e",
+		tag: "56b5f49be824c7a19b19faabf0787a87",
+		in: "ced52b76c057872a60107194b432cf04b7be05e65209045d2952ea0284d8" +
+			"3e2ed5a15cfdc58071204573c18ab03765b4d5e63a601419e039c42075b2" +
+			"7ebb2827de9c6233d6632e6d3db9140bdb4a9291d53f33734c2dc8e24df9" +
+			"0764dc10e0d321d20fdf659bfa2a81bc9e04fd0f83448143276647c08bfa" +
+			"dcfe3bc23898eda655c9353693ed7b022f43eefa23c21db7660c5029ca64" +
+			"a6085d93029ea6c43197356f56b7624d4819f5008d053357d981ffbe7f40" +
+			"96d6c55d8417002d36189b04bbb2c637339d90f4910a400833a8d422d88d" +
+			"c816c1636e8d9f7f926c244a28d9e0a956cec11e81d0fd81d4b2b5d4904a" +
+			"d1a5f55b5ec078dcb5c2bc1112bbfd5efc8c2577fe6d9872a985ee129e5b" +
+			"953e9cebf28cf23c6f9c6a5e09cb09ab586c6a50e4389cd3110777591d7f" +
+			"0608a3fd95b99f6ba03984fb0e13c6bbbde3668c59f2f2b69d7caadffa94" +
+			"6f67e725d56280e59e66dca025a18d4616e81abd9801835bd94485bb2025" +
+			"dee81fba440005b181ee81dc1d7796cbec92e4ec1c9016c8e8073cf281ce" +
+			"f749993f09a618a4671d58b476feffa454600f82955c591882715148a826" +
+			"586f68bb50059914dce1c1c85e5e3951647c9964ec9316005209a58baeb5" +
+			"2c6d01e6b4c275c0050a7e2bdc52133e433b050a700b556d4314e5c041d1" +
+			"93ee47f47adc971aed1b63259dd5cd4f95854a71a947eae3d3d12d0d7b52" +
+			"c6cd2fef2d2e892607a9681d73ac3236fad21ee30a4f857010bc95c00d5f" +
+			"6f0c6b3fe50cd6452be6eec4f5f01542dc2cb5e2db1f52224f11348fe2a0" +
+			"5d1e5885f1317f2d06ce2813dc4c723008e836a2ee95d0aac66855fe4c3b" +
+			"1b2e02ba0700be759b1ef1c2a3123ee4ccf9200d8d4de5e0d503f04c2053" +
+			"66393d1e91b648392ca28389d976aa618b4796acbfe8aa356ecdce1f7786" +
+			"bf09af226bb9402317b6fa319bbb9248d8ce00b1f49f066c69d4df93266b" +
+			"938342cd7fd4b07c320c2409ef72d8a57c21d0c6d6d493f7ca94d01b9852" +
+			"e4fca6a9291e9060154bc38af6c86932645f53914709fc90e11db56ec471" +
+			"6d600ee6452041248ea8244f79534f793bfc1f2020855d817cb4ca3c48ea" +
+			"7f6441ce9af9bda61936c226d810086c04a35e8654fdc30d4b35701adccc" +
+			"016d5895b2121ba4066e44d694f6371d97911786edb73dc3020ba186a01f" +
+			"ee3dd6036c0e205a8d05979bad228fd12c0fd2fded6c7f1e4c11354d266e" +
+			"d9c2f706269c43cd90504997d93a17b39b10dab0ff083ab3bd06540ce612" +
+			"d08f46ce75a16ef330525737410a0d98fb3d484968f9c12edcaf50103fdc" +
+			"c14128ea4ad6c30b56247eab28197fe617e5f88afa5cbe003c63d423647a" +
+			"d3042626fafd2084a0582ff1b1efdb5baa162662048019546234e2f6b6a1" +
+			"d8bb971114aae41df7795b4f3598f2af9e8921a9aadc7fab6c780aaa32a3" +
+			"84865a4ccb02351dbc55ec92a3152d1e66ec9d478be5dca17b4a131b4a0d" +
+			"3d4420fc6123fef80fd56ca266407d58a7880d6b7e5ce2b6bdc9a3721071" +
+			"7feec573d83c83a2e3f7d4023f2f68e785cde728fdbf5054060e4c89faa6" +
+			"1c9dd10524a08811d15c627b3b4ada549a3fa1d8dd77c005daaf2addeb10" +
+			"0abf694da8dd692f113965cd6366a5a7b0c17e1f2a320243e2c90b01418e" +
+			"22426d0401a2c8fd02cb3129a14fdfa6cbcaa1f1c2f17706e9ac374a3458" +
+			"777761e986ee4c358d26f8e420d33230d198fd86704e77298dd4c40c5205" +
+			"7566ac0cd92993b21937c3a3b4a8b89110a97cf38c781ad758bdc28f3565" +
+			"60cf3acbedfa8e05b396d226ef619746e8e4fa84c8e00a7f0e6d652808c8" +
+			"9c9b123d9bd802624cfa949eb68af85ca459b9aa85b81dbc0b630856cb9d" +
+			"7e18cdc96b3c069a006dd5b716e218a5ed1f580be3e3ccf0083017607902" +
+			"a7967a02d0a439e7c54b3b7ca4cc9d94a7754efba0bb5e192e8d1a6e7c79" +
+			"4aa59e410869b21009d9443204213f7bceb880ccf1f61edb6a67c395a361" +
+			"ff14144262b4d90c0e715dbefce92339ff704cc4065d56118624a7e429e4" +
+			"cadf0b9d2e7ffc4eb31c6078474a5265beba0774209c79bf81a930b302bd" +
+			"0f142534a6ae402da6d355a010d8c82dc379ea16d49b9d859a7de4db6e62" +
+			"40f6976ae0f47bc583b327df7ec88f5bd68f713b5d53796e72e28c29e843" +
+			"6c64cd411d335623ff4f5d167f3c7b8cba411e82f03714662425c8e1bc1e" +
+			"fbf435d28df541a914a55317de0ded8c744a1c3a6e047590244b207bcdcb" +
+			"f4bd1f9f81210deddd629192c58e6fd73e83812f084ef52f21c67bea98ee" +
+			"17554437d9642e2e",
+	},
+	{
+		key: "b41210e5ef845bd5a8128455c4e67b533e3e2b19dffc1fb754caa528c234d6a0",
+		tag: "72c9534aec8c1d883eef899f04e1c65e",
+		in: "7eeca180bb20d99635e36b9208221b2b8ef073fbf5a57f5190e19cb86c49" +
+			"89b0e8150d22ec3aaf56f6ed9cb6720284d13a4b0a34cd3d7f7fc7089326" +
+			"6d1893fa4185269fb806677ff490aec8f889896fca50d6c80d295875b1d5" +
+			"4a779b6d49305360b31011b48537157d0f323ff4e865d46fba6bd23a06c1" +
+			"46878cf9404360d325432312ff08ce495edca63a3c93c44d79c050e3f1de" +
+			"4b6ca5fedbbd43dbdef9ceb26d440a59c7e0be3a8e461c4f15b6b1e1dc36" +
+			"a71fc723ad593fb903e83d0804ce497fc49bfc6b6a602b9dc6e9891010b1" +
+			"4ca066cb1c68044c1ad837c638076dd3708078509cba49fdc54922cdf5d7" +
+			"715fb43e9b5a5942cb8950eade143577bc9dcedde58d51deddc70075e452" +
+			"bbceab1e95b5d003eb96bea69687faa6d50d9c605769cb4287b5d9924dd6" +
+			"8881c699abaa6f93e41dac7639cdbbbd0259099a3ed096f482a1fa322b15" +
+			"ffc379812c74e09e95f1bd3706347eac421fe56895e738a47fcd3e118773" +
+			"c3a7e7e264cc7ff5a53a80e436df058265dab9756fdf6913786a47e98bbc" +
+			"411052d58ffec9ee948e28cbaadaae471c5d828eaf3b3c87d3bfd495477b" +
+			"403da54f1418a15ace0d4d0df68f6a8f2b0457b127d5eae1f45ae055afa1" +
+			"8f058d5dd7eea559de3ae9378ca53f7d6dc9a9465ea1f945295f16ee0404" +
+			"7fc9dd3deda8ee32631d7af70c20edc1e12c5f8abd2e78f43dbd4cd6407f" +
+			"038efab144a24ea8a090a7ba3e6499345a60106220c2959a388e1a73d070" +
+			"1d854bfaaa86165a5aee934b615ac7f45da7c43a1e8f74613917ed10dcd2" +
+			"27e4b070414412e77851db5bc053e5f502bb4e2b2645bca074c18643e814" +
+			"4caeccb58be49ea9a552913c0616382c899635eea79a166988c206b9aaa0" +
+			"977c7ced89c4c7aaeaa8fb89b38030c44530a97187fda592b088198b63a5" +
+			"2dfad59a0a4c1aadf812bdf1881924e8b51b8fd4dbca8e73b2986b3ab484" +
+			"171e9d0cbb08be40ae60de8818bd7f400191b42c7b3200c27643f06720a7" +
+			"e0a17441f34131629388ac43955b78c31ea6602a70dd665f872e7669e865" +
+			"f6f40e634e8772d747608cd3a570e1726eb1ddca64f08582b022bb026eda" +
+			"6a913dc83f174ce3c18b9fc0503d3ac74e2fe45691d6dfb4af8c86d752a1" +
+			"6d6664fab4de08afe8858392fcc35cb9ea82fc42c42d48c0c0556267ea0d" +
+			"cc19b10f05e0318c4488ffe704b5036908f5cb938eebd3163503acaa874f" +
+			"592d945448fbeb93a877a26a72306a36e181745ba300afdc30cb7986919f" +
+			"3dbdc5c47ef1fa052a9e4aeeda3955f61ce2f30a0593a81dbaffebac5a49" +
+			"e5a8d1308352701d1ca9e620a67a89abdf5f0f8b1a0acfde5819981d4b77" +
+			"58799c0fe41030b86754837712af821c315301aa8dd50d1387b9fb92ee63" +
+			"10777e08229edd54e5e86b086ac281bd321082ef46ce298a6211aaa3aa4f" +
+			"6e55b5a4641220ec94cca73087760da1b1ac3e0da3f438214e691aa184b0" +
+			"535950b715a64d11485940dcaa3f72e0aa521002b1443f5e7880e2a85b83" +
+			"40d32db0fc4c4702e10f0fa24a35da9307850e945f608ad34d6cfdf6f2b9" +
+			"ff4f6b8e9eb5a883546578e2ff3cc5787322e4384640f42dc5bd05f432d9" +
+			"610dcf7c06cdf34762dd2a5e805e24aee8cebb3b4db9e4d1471da995bba9" +
+			"a72cf59ea8a040671b1d8ce24a3dce4fc86d2df85c8ab5e1eb2b0567c186" +
+			"4fb464f48c3ca72c7df2749542ed4d4be51b63769012ce3d06356856b2a4" +
+			"24995a2429a156ad93bc79c705e7b163149ce53a42c34a19680dfe4fd0f7" +
+			"fce38c30dffe9da9bc941d131f435c1398f8284a230e9d6e3992710074c3" +
+			"881d03aa309a9edd0fde7a39c33f6455dfcc5ae3fa20ea0e0d6549a43536" +
+			"b4cd8a2991a135b7d7a4265fb840318813091274414108f13fe191db7774" +
+			"6a5f4270f6d51a29ff523954f84cb76131d4abee79161dcbd97dc1ef24cf" +
+			"db1fade057dddee00a1e0de0db1afaeed1b535f7bb402afa3b297551fd14" +
+			"8c8f3e05f1351d3a8ee2948daaf14e7fc448c4670c906ae076eac5a7c656" +
+			"fd5f9cd937b91e26c9e5adb43c138f8d65e447b0022a524e059f879c6e27" +
+			"4ff7e671f75717233aae70853d5bd7bbb41b43c47bb08d6dc2f54f9ec606" +
+			"9487d1267add72403d01552a3d138abab9ca8a0d2dc32439759aa5695f70" +
+			"1a17d28dfb85850fdb55fddadcdde4d220e4b05821e5736d346e7dc9c945" +
+			"72743366488b1de8975184771361894b6520e3407c5c2e38473430969e35" +
+			"b106024da8618665d58c9d084824a28991a33658d6ec702139e01b65b7d0" +
+			"cc537a644caeee880657803d95f5f67816948d5ab362922f8ffbd531473e" +
+			"b0ff8fde2afc37a4abfa28dbed0be1b3d4ed48a1d02358e8403905d33b12" +
+			"3066e7a9fe2491ee9eb24fc9de7dbd322c8ddbc5ebcd0d92cd102ebac96b" +
+			"90e2fd784fd6d4b699304df23b17d963080a013794322690456be525c071" +
+			"b78fcd2d1148026e44ff14c4d0f942cd44d2b3263f4a93b79ec7a618b4b0" +
+			"d77ae7a1f6e6c7c7e2f498b825bf1954df348bae45ae1d7c87b6787f1212" +
+			"60c9a724429a4a2491ef989f65acfdc72fa717486dcf1984905218e11cc3" +
+			"970a09d71061e6df751f100abfbf",
+	},
+	{
+		key: "d9b0dc303188756312c12d08488c29f43a72e78714560fe476703c1d9d3e20c1",
+		tag: "6b9782f2a09b59653aa448348a49291b",
+		in: "dbde1820035997dc8a8ff3015b4e0674e7ce7bf0c2d994b7977f2d91b49b" +
+			"f200995040daeb1218a0f4307b6b8211913992b070d321bdb947b4ba5017" +
+			"a0885e7e5502710a75cbbcb56d49e1bdc2bc2afa5a0e83851162dec41340" +
+			"bafc41c5e11fcbf4ea2ac45bc57def4742281bbf734777f83c9ae1ea3d5e" +
+			"d42380230570f59c40d5dd9a2d89b75fa3c92664f12a274d965ed8de79a8" +
+			"b37f3763939ad21d1703ad794f617c8b32b20cc4dd7c1b7f969a65e1bafa" +
+			"f6c43f30c9eba256f10201910e2cc31a9b13a46ad29257024ef8f2ee29b2" +
+			"ee63cc5b6230ab9f87cd5cb534f4b0bb08a790466e0d57b849fffa1ed21b" +
+			"fb0b27804e3ff9df7bebf14e100cf91691a493e53870abfad6321f6711c5" +
+			"0fbcf1f0b2c1e5231d6c0a08e710525176355f6f82bedc1f787f0d3cb41f" +
+			"a11e91ebf9f4cbae46035a371232d63ef0d8bda0355af8cd0a2f7d1327d8" +
+			"0ab769ea0f1da0f76ec99cc737b5ce84675fa8a9ac0c98342bb82b5848bf" +
+			"656d35327ea01a1b09d84ab974c307511af68a30cd6978b529a8f58c68a5" +
+			"9d476062ace8897ec0d1a90d5d167e29ebaa6f46d93d697760c8771417ce" +
+			"94c0f3698985a98702833d1b68641b811840ca3d935386dbd4600fbc81c8" +
+			"728c4fd0e4588be739a048f03bd4ac651ceecd7e2fb120fe7190011f957f" +
+			"cbbfdc025f1ca0b356208db8cad87fcd53c5d3a30a7c2a48140ccd4cdb49" +
+			"f3961cef742caedd1e848bf3cacafb0da030416bf3177877aa0bc5f9d1cc" +
+			"41fafcb829d5e3ace9394028683d712552579e024084a6b855830ad9f567" +
+			"ff58f05d3ec263eddd6f56adec378f167e8dabbeaf7d0a9e65c71660314d" +
+			"6c8d54beeca2711113fbc32a2ff8c0daa8373278d10085d2a0660ad53f4e" +
+			"1ade74a483be180180acf9e9ad3ea5bdd9162ccd69599163a451c6837d5e" +
+			"a5e115bd9a560f395128ea002ee739009a44fa46078b18959933fb6e866f" +
+			"eb4612a56ce93b1affcb95fccaa18d71a148582ba1412a5daa07404fcb39" +
+			"c3cb4a2519cc506c1172c6c326016ae2e5410f6a438569f35a50d45cbf3c" +
+			"c46188651aa22c257858f60649cee8c05c75953ce49358dfe5980445fce9" +
+			"614ccd16d333ad236e29d204691ca0bf46f29da954bcaae52e41016556d2" +
+			"f4cae1d37565bcbe84de1b49f344d0200478a38187da29c155cc98184d9d" +
+			"33dca088d70054e0fce321f7a90c48a14963d0ace2b4e7a24b21c14a5e67" +
+			"1994fe1f7d22d1135d4df9268dd18d323fde3603288735626a5449582d35" +
+			"30e2c2225414e05a8c7b987c873a82e272a5d83e59b90f3d7264631d6ad0" +
+			"4a0cf3b5e96596a66ed5bfbc24ab6e4870aeec0acbad2cc5affaee06de32" +
+			"dca06f175bf763cf8e7fdf95941a177e934f0078be7dbaa4c9b6f5c16b4a" +
+			"5607bab5d56144a6ba3c7d9a084b8d1f4b24b6f9754ed207b230d3a2cc26" +
+			"259ccc725e1f8a44c4df8143e13edb5ebf073e2c9d2da5f1562df4feece2" +
+			"f6480987f093f642eb7afa3aa92dce2a8b60bb925cd2d11cf6c2ae7d2153" +
+			"1a9c8f068d71d0e682023932fe64e956a49347aed22b21084c4a84480491" +
+			"244ac6b337b6d12d5551ad5684766c68bacca62bdcafab6603c81bdbd8e6" +
+			"80d9d8b3825eaea4df023142e840f98ee251466a0422d810a54726a9f03a" +
+			"7e0afeb0043e60e2ba4908f951d2e87fcbc372096f2a9f4f2a95ad5faede" +
+			"3796b11ecf4401c3ee3d268bd8c46476c61e0ffc5c43c0f3c58c79e20f75" +
+			"520c102aa3c260972a870fc50f8841fa0553a9e30bf37ad282fb51b34adc" +
+			"7a933ca1691a8a706605ce0b906fdccbe954f8e5f2f63c42599a483c4be7" +
+			"3a041ef90ad930fe60e7e6d44bab29eebde5abb111e433447825c8a46ef7" +
+			"070d1f65862b30418efd93bfea9c2b601a994354a2ff1fc11c383e7bc555" +
+			"9e7546b8bf8d44358b1ce8cb63978dd194260e00a88a8fd17df06373aa80" +
+			"04a89172a6051bd5b8cea41bdaf3f23fc0612197f5573f3f72bce39c9f89" +
+			"faf3fb48d8ca918586d4feaea7e0f2a0d7a6afca096a081af462ea5318cc" +
+			"898a9cc09e8258a837559570cbd5eb901e8c0e04ee88ba31c81a76b000b8" +
+			"0e544feba576b3eb5272b53e46e96a0b35b9c759caadcec61444f8ec47c3" +
+			"45a1d2304e2708eeddfbfa75a98eab3493889047d690e84431d445407fdd" +
+			"99560c0bdd287e0944116f8ac62ab992ed3f1e2b415aea784b03c6904795" +
+			"f4326ff60bc839615f2894570dc9c27cf928ef192047528a1a19ec990978" +
+			"3b0d1a13dd4baf4a19e49bf798975abe2ad167dd574b32b3d0c22aa4d9b5" +
+			"2761e8f56cf2100fe5a39fceae3d865f3724d4f299d07ff899fed6baf7fc" +
+			"eb7189357bf56cf94a6493e61301b43e3ed158cb9c7a0e615fd9888c2db0" +
+			"7f7689762f62ef6b3ad4125e06b07a422f5040c3aa8b8f205d68356c9225" +
+			"56fc4c976165fed9599daeb297498ecf744bf6c7dc5e30604c461ad99402" +
+			"2eea0fb6fe33f82a97b5c272fd24162a94b761ec7e52173e7bb42e88b343" +
+			"64f5fa2c141ed04a86b8d00fd9c25bf77a8dc3e63f5543331405be6bf421" +
+			"6a891089b316aa4f887cb4aff0dfb4e80c2ccd65ddd9daa74b17b4411c0f" +
+			"c849dc748d9b138279dcd9ebfc6e6759a53f5c28a41bb82107d71cc161fa" +
+			"81291a8290",
+	},
+	{
+		key: "fb70ae7ec12264ff9f51124da188e5b11dbf53cae2671363f6054b575b1ddcc1",
+		tag: "d9ab81fab28b3be96fa3331714e78c9a",
+		in: "c62edf20b1d53962b42386eb570b10378f9764421ecbd7c4802853332747" +
+			"19ff4c89c06005050fa9ba6579a844060eb7ece6c43bab520e683e0f36ba" +
+			"49cba259edc6ae35d41e0d7812a7d5edbe4d90cd5e0504d16f4c3f70d01f" +
+			"5a0313de55934b661ce1ec317968c2c4de60f45c66cded8c10565a1ca6d2" +
+			"3a84bf182df2fcb05956ed4d46b49fc0fe3bd23961d9466fde070341ce41" +
+			"bc6e148449360a31634fe10e91082d82def90d9da2c250ea72c58add2058" +
+			"d046b4392b78bc3af5b3936ed568733e8ad5672dabbfa3130a6a535ec73b" +
+			"da8e7223535f49f96cd35d56ed4792c5cb7076720d5461d96a2692b2ada5" +
+			"2be08fb7bad15d15a0108143790024f0f15f5adc275e783aa56b70844061" +
+			"e30952a040e4cb9650f2a010417812790105d8f58bd25d99b0db3cb16229" +
+			"3f6322e86cd5b0bb1505a7b998fb0f81d1e1915faca3c2c8ddea39115507" +
+			"80339430a7955521839deff5b301f3fad54edd5ebd2ac4ec9b1795cb4dc0" +
+			"e2eb62ebca8e886c3f1e507d10a0228c3027b472a7104b815f5ec8dae55e" +
+			"0783ff7ae9a3e6b99e381ad788206b135520cb870ba0cdbe876feea843b8" +
+			"5a82adc95a6d71c555f798da92b82daf0abfcdbc82ec30b1f12d78490b06" +
+			"7315735017a94ac150b44dfaace151896f873923310ffcd41e91bac04de6" +
+			"d70ea71565948c907ab21c4a23703fbbd2a8de6d3095f3d8f901538968e3" +
+			"60e7bfddb9d22036b1c23f4f5f1b2ee22623426a2d5de68c1e1a38e38e08" +
+			"e2b5670aac1edff69e9c73c2ca56cb69c709009ef1d541aff1fdb2b40c92" +
+			"9b87f162f394b76cdbba1f5605993e4dd9c312321d59b0aa5c6e33be1b10" +
+			"bfd00b92d4c02db064d0e4a98f2913c89051b0f0ead163deb5087b6466d9" +
+			"84f57553b0fa53850eaa142e072fd91802eb9f0d2eb7318dd620555e6ce1" +
+			"86706b866d41cf6ba81f100342faa14d801dc6f3d522db38fab17a879fcb" +
+			"b6acfe922163505bd23a6842f6ef6397ae5fb6e6016421998bd43b0142b0" +
+			"3ca3b16d6ccb7a47891c75c687d791a930b26aaa2e3412e7aa16e2cf1501" +
+			"7bf6df6d2e1c289af0d7ce03954a60c1dfcee5e4b3da51eb43ddd14faf59" +
+			"082005d0c8b104561f66c002ff426be60be769282fc5685cfd1968df1941" +
+			"73667e48e9ad681d35757f1199f1d93377bbad093c8cc3efa2bcb6ecb703" +
+			"694422772d15aaa58cab9e9ab277ed510f684114cc4a44ccadb3eb1c9a76" +
+			"d8619a9b7743106df6fb6f927ac49b22ae5bb9a9a4d231e340a2cd0e3282" +
+			"53f6d75df694826f60e4b3e758398793eaf73ef5d4b56cd1471e16400f40" +
+			"4a947e9737f4f874fe09a29ad799f4525156e3abbf0585c3c3c0a3744c86" +
+			"5d56db3d2ecba6bcbb1adcc8bf5f3b2a2d46d3eba18cda55201598a8112f" +
+			"d8f14e205f0e615f081b8ff6c5aa6669da776bfc7c34d5af4d0b26d0d819" +
+			"f6aacc53cf3c6653138b9a962acee9d6ea01d280c35bb1f05d1509238ccf" +
+			"004c5013167f804d1780d9f4ef9d45742fccac346b0472bde24ff5db9ae0" +
+			"16455a3c02256358fcd8e6a9aae94f8a37a1a3da58a889bbe3d295e16544" +
+			"2e580f59bdd31c92ffcab40c49c1cdbb4db1dd4882b66edc10fcb1704203" +
+			"c518c1d8d4c268588ce13fc38e0210aeb47d11d2603d4b3de5c6ff5e969b" +
+			"9d5904abb282b699bd04a6e9f1cb323679e30400d725aab128a032745dc0" +
+			"be05a46b02b34b93bff02523cd8498c021fc35a488f164a70ef1ceb873d9" +
+			"14a681d3a3a34cc76bfd5a547e2630d7741a284511bae5897d9f7a197fc2" +
+			"456af5c6cd7e1a93d3388c7a990b5feacd7749cf39fdecdc20adfdd540c6" +
+			"9d330195db7cc0d4555ea5f5356a3647e2265399f153c34ed1e217c5dafd" +
+			"c2c5dd3d566c332c7ddacb0d76ecd3a0ad505a4165443aa81b0f43cabfb4" +
+			"62942fe74a77c22b8f68a8b1a6d712d1e9b86e6a750005a3796ba1545396" +
+			"13170906d228dabf572ab969c762f8b296054f23d5d4a37bff64bf9cc46f" +
+			"43b491b41101256018376d487fe8097f1653a7a9e99e1ef2492600598fb0" +
+			"bbb7df8270be8b9106126d6f491f8b342a96ab95df6133e883d3db4c6a99" +
+			"402aeb58d371263a32dcf76d33c8904395b9cf0016fdfc15608eb43e20b0" +
+			"99cbe7455f7a76f69bba058ef96f83ae752587485657f89c7f26fde7fbeb" +
+			"a82ede581ee92821dc13b8202930aa58bd4f1c86f68926baca0d06fee642" +
+			"ea8c652d226af91a9638a0244f1a03c7ce56969b87cd5c1f86110d192e0b" +
+			"98dd979d74acca6c1956b1127d9a1f456053d17974081ed8ced0faa4293a" +
+			"319e5b25ba285c1151214f52c283e39c35af51c4572c8e395b7856697bfe" +
+			"dfc4145ab4ed0bdbe43ba509c06a196ae6bf30d7582550cb546c63b51833" +
+			"cb0dfff7196d83f6a1c6d6d712cce2ec1989fd9ff5a0a22ac5022b49d566" +
+			"58f196703e4809e7624fe7cfa6c13b378f5aac7e66e657ed7eaa942d1a00" +
+			"544a947199f24d736b8976ec2cfb563433c49ba131bd08b63636854219d4" +
+			"c45100c98e3092773ef492dd9210bfd8f54cfe2cddafcf5c05468d90e620" +
+			"0c2ef99d17fa6992cc45eff3072b7cfd51cabb07ea3019582c245b3ff758" +
+			"0302e88edc2c13fc43646ba34de37338568baa66ecff3accfebad88d143a" +
+			"fd1c3b09ae39c501e3f116af33b0b720d6c2baf5acd7f31220788b2f9017" +
+			"3ed7a51f400054e174d3b692273fcab263eb87bc38b1f486e707d399fe8d" +
+			"5a3f0a7ed4f5e443d477d1ab30bc0b312b7d85754cb886e9",
+	},
+	{
+		key: "f7e7affceb80a0127d9ce2f27693f447be80efc695d2e3ee9ca37c3f1b4120f4",
+		tag: "41c32ced08a16bb35ac8c23868f58ac9",
+		in: "5a3607fb98eaea52e4d642e98aa35719bfce5b7d7902950995f4a87c3dc6" +
+			"ad6238aadc71b7884318c2b93cd24139eed13d68773f901307a90189e272" +
+			"6471e4bf9e786b2e4cf144764f33c3ac3e66521f845f6f0688f09eaa227f" +
+			"e71033b0f74295f6ddb91fe741323f2b54f420cb9b774d4291b06219f1fb" +
+			"4410b55900425c5e6fcabec76a5c2424d637a1641db6f0f6cad564a36a91" +
+			"0f49894bfd598e91f38ceea65e8253c1284f210cf7b50a96e664e562f3cc" +
+			"01c4fc490fa6d4679fd63fbb3ed8995a8a05166b573e92d22ef4370c6aac" +
+			"74ae94c94177e5f71143c6f340efceefda679ae76f6ed7f26eaa4848a8de" +
+			"8c40894316efbb06400f9695b18ba279e8947c032a84a40ca647d9ace457" +
+			"6dd0082494d6bd7be4e7928e749c78110af8774a5d43e9c9479964e2fddc" +
+			"ee51146460eac734311225d08c60706e40f298a7cb97f369ef599be097ac" +
+			"3bf1c275497bbd68968a235fdf8a61bc7cfeef0fe451bb04e662ca39f34e" +
+			"a8e3acdd0befe9762f9eeb275c0cdd43c80fc91131d1e0e790020975ab65" +
+			"afbea81f303ebd86760821efb4cad7cc01fd6d6fd194ac5ffe7703d890d0" +
+			"169e21b444cdbaf691fc741a5d99bd47357c37785755fa72582ca4754a03" +
+			"b4def86ded39aa6d9eb3f38801077e6d17e3cee3fb57ae83f30c79c3cf29" +
+			"0e2739c6b7323612cec3a561ebeadb4faa642f150323aaa9d270658c907c" +
+			"4c1610a5e1834730c08be3379cf1abc50c30e2bf01ce903927c27d85e135" +
+			"3db9e216dda8860c45925e2bb791abe5c8281ee6d16607bdca87f60662dc" +
+			"bd6e20224e7f009a86db66fadd8e37e0a59559328385090c6953cd20bb61" +
+			"f28a734fb056714f5159977f18e5c5f11de75f7a00ba807e47a29e4da32d" +
+			"5c67ec76ce4d7b669b5e6ee17e1df7c673dd8a7c87fce665cda8adb9547d" +
+			"1dccbdbe7be44846b4b121b0bfa65e4ed530789510d79bc4477e50178060" +
+			"f2668ac8956f39ef422ecb0e4cf90b8ce508552eedeeefa6c7d1bccc077e" +
+			"8088bd7e0e6aaf0bda9f11c412c270ee2ad6912f9808f9344a4bb137bdac" +
+			"b5b9372b00b0de026a8f5d1fb13972e1290b5005689f7636c43aee2fd443" +
+			"93d390371ae573f0e064b2d7df552b9adf04bf173d71c621795b9fb503dc" +
+			"5e918536c6ad25ce4a76f70e6b752b6d44be321187269a19bcf33ec899ca" +
+			"40e88b4eb23217095a85057bf95d8a54812cae4a7d32e0c2966a21376110" +
+			"74c6c8c3dd45a553c43c675d23308709f91be0b235d0222aa5e1e1ce08f9" +
+			"c6b45ceb5b47bcd7d7b2d4380bcdbd6eced452d93e6d8cbe18123277889c" +
+			"7f86b15fb991364a501fbf5d8244f2e3332ea0ab49e833c6f765017a4006" +
+			"cc7cd1a0365945a8d8873cb21832b210c83e451c01ac949de2fb0f7a420e" +
+			"405bf64eb251c6f022181595d68174b91e503187d3b3f49b60c23e44ea40" +
+			"ca20311305b413047bb22e89672758b74d6bd1a06decf09e9556421087a4" +
+			"0c1d2c44c5fb13d4d9625581ac4ccef1a1b5eeb5689aac5c0291aebda276" +
+			"50daf9d4396a64d02c6d58bcbd609d9a0017880ae0cbaf02ad0f1fc8d1b3" +
+			"ec987ffe13102d77352690c9b761bf13ea0b3a8ebad4a0823817fcaab4d0" +
+			"9b0bf03486620761dc77a6ba007ba07153b17425c4026597473e78863cbf" +
+			"430c0e5e9b04a83ad11506b61b8d9be3aeb06b5114e0d53d4724863eba12" +
+			"4f3b974bdb0d02743520409910621cd730c97ca984fe2921c38055f83ee8" +
+			"c4611db92e52d8ea51d89203e89df7586c574df15f3a96ed5a10bf04cb27" +
+			"f9656b5b11cf35fd21360b029ab26e9a741c6b3e6357aa1a41de2cac6e85" +
+			"f9a49e3441e60a60e74f434e1b8cd4454b11962e5507ebf904e9d6c52a7d" +
+			"9722300517c434758fbd6191f4550108b143eb16c0b60094fdc29327492c" +
+			"18a3f36737e506fda2ae48cd48691533f525acfffb619d356bf8347a8bbb" +
+			"4babdc2ac866e497f192e65a694d620687cfb4f631fbd6ae5d20ac2e3a12" +
+			"4d85f9391a240b616d829ac2adceedf8f3451ee77e4835639b13c622ef8c" +
+			"48a181fc7598eacb419fa438d4046aa971942c86b36eb8e16eab67105783" +
+			"d27fc56f5b66f35451b2a407d4648a87ae70807e45bccf14983b3abcb198" +
+			"d661d562dfcb00ffc569ca967171746e4e36f839946bc7d2ea9a0eda85b5" +
+			"a5594f6a9c1b179f7230eaa7797a6aaf8628d67fd538050cf47aa654778c" +
+			"11dbdc149458c1ec2233c7ca5cb172356424eb79479b6a3eed1deb9f3278" +
+			"5282a1034ba165032b0d30733912e7cd775cdb7e0f2616b05d521dc407a2" +
+			"ae7dfcf46fbae30547b56f14dbb0ead11b3666666c45d345cd5dbfa200ae" +
+			"24d5d0b747cdc29dfe7d9029a3e8c94d205c0b78b56d5e18613b3169bd44" +
+			"1b3c31513528fe102f9bac588c400f29c515d59bbcb0725a62c2e5bfb32b" +
+			"5cf291d737e67f923080f52d8a79f2324e45a3bd051bd51bac2816c501af" +
+			"873b27f253ef9b92ba4d7a422e2fb26a35c1e99eca605acc10d2a60369d0" +
+			"1f52bca5850299a522b3aa126f470675fa2ec84793a31e9ac0d11beab08e" +
+			"2c66d989a1e1b89db8d11439ad0d0e79617eafe0160e88384f936c15eb15" +
+			"ece4ff00e1ba80b0f9fb7a7d6138bdf0bf48d5d2ad494deae0ccf448c4bd" +
+			"60f0788d3f2b76de8ad1456f7572bd0ffd27bc2836d704d95e9c0df34571" +
+			"9dab267dd805577fafda03b834dd225ad9714d2bd182b4103faa5975180f" +
+			"90d5d6cac1825a19b9d4c87cc825512ae9dbeb33d2759c990905050f960c" +
+			"db3eb364c15b593524c882902b2a1d7fe40ea3f54fb0202fd8821463c7e3" +
+			"4b02a1209ba0048a9805f0468a13e03d18009318ecd92042959be263a51a" +
+			"407f1e660632c4247419659a4e073a8e9cd4a226763a7daea464d5427270" +
+			"7efd053cb4efc0504602c4f63e7d247b55db2ce1c07138f585d16cec97a3" +
+			"0731d5aec2166cb4de41695feb76280cbae1af8a2e67c2d5a3ac5487ffe8" +
+			"640f308ace6137e83576b79d586b663122221c20aba7a6bf60f73958f436" +
+			"59f087f850ba6e2d7fd862249c5fa6b20e3e43d4f2aa10d4c9cebfcbdf02" +
+			"6b8d103e4f89b93dd8af172f421001c8b162bd6d0b847a58ac108b6d6cc4" +
+			"9c7a9ba069deee",
+	},
+	{
+		key: "e3d21f9674f72ae65661aebe726a8a6496dd3cc4b3319f797e75ccbc98125caa",
+		tag: "3c95668130de728d24f7bca0c91588bc",
+		in: "baaea2b4b4cbe9dbc4fa193c376271f40a9e216836dc35ac8012476e9abd" +
+			"43dac6b9ce67dc6815904e6c84a5730cea0f9b4c6900a04ae2f7344fd846" +
+			"58a99513ffb268c6899dfe98d605c11e7dc77de77b0d30986f3051754503" +
+			"7c26be7b719aa9ca1140cfdf4c586b7fe726a8bc403249396a11cfee0a6a" +
+			"f6c5e72259785cfd13c2897384fe527100170001ea19106aed38f7d5d9a7" +
+			"ad43f0b41451e19989192a46b4f9734a774b6304cb74feb7d83822044a24" +
+			"2e51d55c0b8318e0439493bd1a57cc13f6079166cabc46877d003dcd39b2" +
+			"c0b90f6b32fc77acf04a6c125e11b35d91e2b18401cd53df4aff804e3c67" +
+			"a8bb3894b27c6e9b0070b53a85aafab0c0a253f9cfd4d3cd3be52428385b" +
+			"24a3f9f71660ca2c38474d14a0309e2f400e2c21af6e379099283ff241d7" +
+			"51da5a96a8dcbfdc43b913b29cc8cf8020eebb4a67f5bed31f2e383f8656" +
+			"8c815ff172382b425e95902e80f5fc219eccb51b656d37b56660f749e5b1" +
+			"4976a23648680a472d02ba71476e0afb29a0e084984f4eac3befbf8dd802" +
+			"2b7dca4dadd18bbe58e49c49ce48a06a71557a9a620c51e2623f818e4d62" +
+			"c2564c7ba04595cc109685869b183faeff2ac7a65049fc57cb10fb01951e" +
+			"a525332782d691f9759ec2ecd68bebb9c7aece5d522a08ce7830be520db4" +
+			"c9d60a2e490eaa0c91e37b256a97f84b39fe3c77953748c3b86fd84e9547" +
+			"a298c049cb28b8c85d59548b8dce635d59487c9de615802d16a8adc4c0e7" +
+			"80f35b9f10588a431b39b499dca929ab9d225f26e5721820627fe62427fe" +
+			"06d5773a50878b6effe840dc55bd3ea0c35168f6b6a972d57e8f88c5993d" +
+			"1ae33e0b7e9459c123753b518c184de7aaf429df078c9a18a29af77c727b" +
+			"796f5c1a501fa8105ee873c4e78c907142eb19690638a182fddb413adb06" +
+			"d66db19c7f6f46dac582bd72a6347b4427a576eb769d233febaf7be8f768" +
+			"337273c12253924f15653f9f3602b783703a81454a1dd7a8772a9ab1eeb8" +
+			"51be33e0c6c0708f3cc2012cabe8e2f0c38e35372abe27bc148fc4e1054d" +
+			"9d151f80aec0232a3a92dd77928a3678ebd7d09ba7b4e1d83227257292c0" +
+			"b8bc4a76de36bff6c9deb383029afaf4f37d5b935dc080a18665545e4acc" +
+			"195da0b9545d8902408886204b64f8548b32d012e0cdc520c17d9fb3be97" +
+			"800c2e2b945cb09a75a0a49e5d4d81c4194d91e839333b2b9b9e34d588e4" +
+			"e20cc1e911ca0a1429fa70ff063f0090fd842f89dfc5cc44affcce4e1e1b" +
+			"8b11c612f66b074c03ac2a055fd8f51ac9ed4f2e624589ff5730721d077a" +
+			"fb4c19e43abf8cf3ffa698362be8be51e92c2c91a4a56be64d9ac6d3fbaf" +
+			"5536a24c7fd0adaf74ca84c508e5e8c8bf7d4254e0c44158bd26acdf3f64" +
+			"e78438b3aaff89ac9986cef1e3a88d5bf2016340367a1cacd01ec167ec6d" +
+			"185d93a2a220d718b43ce1d429d2cb598605660b030e51e8d75fdbdd5b8f" +
+			"8677675e196a40a88285b18b24c5d2d594bab3d457e6f9e503e38cd470a6" +
+			"9ff8037c9a0a0f110a434335d954fa856a3721e0edcfb14287c3dd9639ba" +
+			"4db32b7da0670dd0a872e468e3819741d0d4ecf0a4f7a011bbae1493c01e" +
+			"642757491189f8664be3ec6437c4f3c76abfb0276e44a4d28871d3487c2c" +
+			"ce2f230452cb06184bb8620919659a7ba0a3d5c12ec25678b03403715ee4" +
+			"acb6a53d281036d8f3a085143cf5ecc3a0c6c92129caa7ac1f645c7bb95e" +
+			"4f63da38dc319e2ccff4a9006f9b9b1a38c4c39f6dc686bb82d43fb9fce4" +
+			"0c767d3ff22f52c5f9900130c65bb6a9cc7408a777d49b70946665f4a733" +
+			"5099376b276a43dc9a6382bb2d40425f6481b1846148434c672b84dd7a20" +
+			"33deb5140d43ba39e04ffe83659b6deb48629e1abf51e68748deffb756a3" +
+			"ed9e0807506b248a024cd509f539f4161366547c62c72933584e851599b6" +
+			"82ec16f1d79e9c6a01cff6f51ba7f46b67cdca09f3ab8496322b990a6116" +
+			"8d7574854a1cb1cb8f30a303dbd13a095df56dbb940dd16ce79879cd2d73" +
+			"80a419842fa1b34da668286de4c1ff5917b7aaa64713c349dc8f855d04ae" +
+			"de9a3a4d0739dfc36510b1e7bb1695418164285c44631b4b1a7c5798ecb2" +
+			"d976c1a3679a827bf0e8c662567e402bcc1354222036ad5959a6f0b8508c" +
+			"6a8c7d4a63e7dde154d778fc80a011592771d55801c7e1297b00b77f80d6" +
+			"314ebd1f5b3057398d1943599897cfabb65e7568d8fbdfcbecfd4b8a83ca" +
+			"0a7bed08ab9a656424831e0d7718c15727af7c83b2ef5eb5684aa044eca2" +
+			"ba896811246766248b20a325094a4b4159f9cde1ee349be6dc3c9a190453" +
+			"0349212a9537f65ae333c288753cd2bef6c5beb2f4164168d965a2c0fb9c" +
+			"c8c73d9e776e23d53ddcfb83bb7dfe2a1b8c781280f449d6f310faf8b53e" +
+			"89e6a611d6d3f42f2aaed5259730d149b3e7dabdc9f865bc1555374738c8" +
+			"456abe112e9628fb31efc2ecdc972da05987aafce728ccaed246cfcdf518" +
+			"3fe5dae528bbfb99d33194167e0f84d462d3d0da83e92227cf57922c7956" +
+			"4fe44648d87c69ad708e797972c44c4a5183fd5d1150a1182e3d39c3cd16" +
+			"3920f1d7ed83992bc4116d9351ae1c6c4827d1374242e374310409f32d5f" +
+			"0f38c78b6489c568b791c70394d29ea2516dcb10e51bdad862ce3339d5e6" +
+			"14fe14f150961809c36e0a2c8eb872e9f7a1c0956fbc9194cb63ff9993e5" +
+			"d0dcf62c0f49e81dbe99f3656c4dea57b766ae9a11254f9970618f1b33c8" +
+			"f339f440de240170f7a21f03ff2da42102b323ce2b9b7d0de5aae324d1ba" +
+			"c87b1e4c5279a566bf659778f8b03882aded57377a0f1b063af2897060e4" +
+			"23be7cefd4aa9a28479c16773944d254fc21d3e1acdf508b7972372b5991" +
+			"3b8b088e93471a7d54c6ae4c52ba465ef07f19f269677fc2f64d3fb3d7f1" +
+			"9069d6c7001d4b002ed6683c59bd5651a450503b68a4a00820b8c17e3263" +
+			"18f32c21dfbcb2a02a104edaeff67ec09533aaf3d1a7fb41aa5d506ccdbb" +
+			"e6e35fa0a263c0aad3acc91182addf8c5bdfbd0626702694b8d652a63c65" +
+			"8d6b2b7c75d015630de508195e1fca9573b61bc549ca017c4bd888194d44" +
+			"3e031f36170215a301f922736a819f3ffda69117170d1933300366c5f2ae" +
+			"1052446ef7c3b82c5868be158a881597132f51c91c80c24ebf621393dc45" +
+			"05fe057364a76ae67494a8a5f67acb551cfe89f447df272ed9c1509fc330" +
+			"2c3e16541452d4d68438f26858724012ad3b72c094b9f166c6bedb8336a3" +
+			"41e032988f39cf53535789b320b5424d07b6bf5f8792e3aceb0e868765b8" +
+			"611d7905089949e0c273e2410c72a146cd63981f420405bd883e5390e985" +
+			"8214a8db714e8400a21d0636d7e5d9671a3582ab9ff032170b8dd6b9d5a2" +
+			"144d065228fa54aea9a22654df67f3f62c5fc59d68914d8b219829b536cd" +
+			"2ae937ecccdb6031d94cb3",
+	},
+	{
+		key: "84373472e362a356bd5c9b50f55c588d067b939009944f02564f136c62dac36b",
+		tag: "12dd5297cfcec53deae1dd5f9325d894",
+		in: "860d9b2954c3daf18fd67eb8bd9e6e3de2e4988ad9b04b1987219204dee2" +
+			"388db1c59a935de27bce29e7cd3ebdf038785efb35eabd4c3785a62b1d9c" +
+			"3ffa25e2273cfe5eb10b4ec6152cd8f21dea415421b452efc7cc4ea6bf1a" +
+			"b85fa6614e7f6d650125424865386ff8ab53247a63ff023b2d0753a9e5bd" +
+			"458d6ab0156fd3cf2d5002f902f927a847e8c4a8426b0a5191f5e237d590" +
+			"2659ce9be9024750d1d618a6b8dd57efb6c2bbac2930858f1132639391aa" +
+			"9e8a620a2a7d64bb7e943c77753401b5b619d95ef857df25a52b4eb97372" +
+			"a05416706b2644e2687bf1d42c0cf06e5eef8a1fc7e178440bfebb85c44a" +
+			"4837f69e43a1789728a999c5e04291576e757510f22bca11583a4e93688b" +
+			"442f2b2dab8d5ea9441ff09b8287862ca538ad979297cc75510a3d9ef36a" +
+			"662b4b7c373f184202befa5bf3f315642e6210763d033b7e2c59731cb356" +
+			"045e9470bf2f83cd62f11b3e904b0c0b1be99bcb805150ba7ef12b8df3ca" +
+			"bfc5055640687d710ab88e0fa8034b26112ebfd044a4b290b1c6f6d18c31" +
+			"ba9880b1cf2d81b5d02f00d6d351da5dbf47b6a5cb7b53eaf6de52c8a68d" +
+			"053602ccffa37ccb44a7683ab4f8a58c4bbc9e140e4e6f3cc10a5c07ebd6" +
+			"070818db983f9f415168606011efab6b8d7b4e61e8eadd8bfd8d028b89bf" +
+			"b0a16996252d7b4ee4f9ab50fc9d6e482ecf99beeabc38d70efbb9a0d4b7" +
+			"9a1c5d2835adf8e25111352eabd24d562644efc97637f695e4792f2049c6" +
+			"00f4d889ceb951cfe289adf159865d013046985d7fe2598014bf2dbbc528" +
+			"b4166fc2180e724ded8e7ea1c8d66338ec50d955d5594a0a7b4655338b70" +
+			"e8978485a722df814fdc6fd2436dbc060121fcb575672b2a5e454c1209bc" +
+			"2bb21a99d39dcb3c697306dbc2104d60fd8051c43ea2fce268987d0ec249" +
+			"a5c02f91d3b0dfee181b3cf8ef1ba9665daf7ea1f1d3b216e378943b78b6" +
+			"bb41e5dba095748bc776f8df6383033a1f5504955da3f42153b1c7ea83e2" +
+			"f90b990ea0c5bd3906b5c4060b19f447ec7762916b8766e5a23bc4d39cdf" +
+			"8e27752df8129b60ccee1731e47383b589d4fcad865eed4041a186df206e" +
+			"9fb69ab6ea092e36f186a6fea8d77bd7f3ab0fa0e29404d617317c75c832" +
+			"854427848237cfc18486c95f7213b9d53f324da036e8d298133b5003984a" +
+			"b9d71836f9f1b059db90005a9067c261bd85aaeed4d623df2220eb52b73d" +
+			"d683abcdee5cebd411996f853752f638bd28df6d78bec2ed3e00d7beea06" +
+			"2b81c19682ffb2f6abe3a3623a2e0570650c1384f1818d76fbefe3a7ef3f" +
+			"46138160ef897f9934e00e066e215230e719c23905dc60d7fa4d666fa52f" +
+			"e7737db15126d3262c3a4c385cdb23ff3b56c131e43b241f4a6062a1a248" +
+			"de9f13eb82c11f7b6a22c28904a1eb6513cdb11179067b13c7b5f83a58c1" +
+			"4f2753f19fdb356f124f52923249d6e4a2c8dadc8bb0fc91e360155a14c5" +
+			"c194334b9f0a566d51fad98592b59c1cc4b40eeddb34e64f337f83874884" +
+			"0583f853398c343dabc29b9444be1e316309fb8d81304d654b3d4bc4cff3" +
+			"55fc31278fe22e649324ef10acd247c0b72397edf96a1c16bbbef0640296" +
+			"4d219575fd23c36efc1fb8f8a34b510ba9bdfb3b478e236777ef7c6c47f5" +
+			"5a2bd0383d8eed3759456ffcffb15e61985b08c022658a5ffc875821bdf8" +
+			"83f69f096dcc72a96888c3af76db57a54be701759670bf05cc9015f5bf1a" +
+			"745cf755a25b1403a870875701427f820c4b29eccc260f30113629ba03e2" +
+			"785014bdcbf34d0c67aa6aca20d2dece811788686d5a45820d2980bf7d69" +
+			"d5c820a09bad7bd95166f63dcfbe8652565c285e60e2704955d69b3037d8" +
+			"7f5e6567d95b8891276d5cf7c59047d10a02ae4a28794405e2524ec2d595" +
+			"1b36ad1b9d5265fa098a033b88aa66cd9eaf01eea49c7dc4cc51c486f624" +
+			"507a2be23f152f43709b2cfecee44945ca506950e90e70164b77e12e1c13" +
+			"0b4d1021c2afa20038f190096276cd22e89b6e7dd10fd58fa033c9d42536" +
+			"98de3f4908203be8dbf259112f840c76726d982b4a837cae7139e27182b6" +
+			"1b4dfbcc50e42d5ab8532edfbd30f668879824e9ebc34b63ff1526cda81a" +
+			"e38352a774d79f73219500e57f0159a32326195d8895d965071834876a45" +
+			"c1a3c0bc4b1638535f7d40011cd5b23343fc27fa318c1aa3f9d8c43351c6" +
+			"6148dc2175e0e620813266da3000954dfa22048f305244629d512e852376" +
+			"6248a897a3ec3e2983aaa8a0f025f18feea57a5153a59b02604ebfcc7a9f" +
+			"b03e62443df88ead9dee955e23bcf6528c278a353f254c9484a67a7b263d" +
+			"a301923a4efb6866aeaaafd428e6da48781365bc49e90cd16b2388220d08" +
+			"bb9f79d14012b5a8299a651917b6a829488753b6ca449a14e8dd8c5fd5ef" +
+			"657d627b8e7773475b802655dc033694f24376e3b01e519d1aa8365d0e55" +
+			"92d0a4adbf555639b6d75d7ee59a7d12c6c11317b7927f11bbe75ed90508" +
+			"b0698420e231206704d22dd1f1740edbdcaf19a47d66ace4eecbcefb77b0" +
+			"85cfcfaced4d2d6048ce76434eb79990f0898adb4af2c377b581ebab3f3a" +
+			"150f40dcae002d4caa60050591c0de4ba83bfd59a08670beaa4641aa9829" +
+			"bdbb720d6eb8b2f3e864a98676a67271a82cffdca2b3590a0b5f97efa5d4" +
+			"ba062b4798707159782bedc75e5363d5f5d55ec2bef70db22955adf401fa" +
+			"c3b7af937816eb25d54d9f2a92e5a2a04bd8b8d7568204fd289f5ed2e033" +
+			"a76209d288e11e8a4dbb06b9029e90cb186446746853f02d738e06bba538" +
+			"894e03e2658ab3d7f9ac861d2cffdf12396004d1cd15f18812d3803ab9e0" +
+			"6f41c9b374d6a0678bb82ce06d9e3b9dbc8d2e90b8f64d0d040f3fa8a3fa" +
+			"8be71d2b3183cceae1bcbfa2353689d842f7d7052e5699dcc70ab2b58761" +
+			"7041e5aa1e2f41911d525505f061d3ca45152f5a7a1fab50c674e4597a52" +
+			"b46aafb4ba57413879cad1308321843abb7c39696fc2f2e225878bb1191e" +
+			"e151cc76f1a1b8d491c1672fecbf710db82dcd32554361967fc839c8e5d4" +
+			"e488856e1b9382eb3fc3bdc3b6886a3cd79761b02bafa080a745ef6afa26" +
+			"822f1d10d5e8eefb842837d82c9986e78fc3390caa142b7643de8f613e5a" +
+			"890a57f5883409549537f8139534f4ca1b60f33e42be25433f1d82add530" +
+			"6a4cfce258c0d4f1f3c9148ffb5c4b626d51f78ac20bff0393b7fdb4b9cd" +
+			"70fee7f69892c8a9ee089c6c5c7bee0a1b825e5b9517f2c82d6c149735fe" +
+			"45a8839812c2deb2a355b6230697053092eca450b7b0d3242b2689efe364" +
+			"09e820d91fa4932034d96495d9dd3baa4b385da815a7cb69438ff648b326" +
+			"e7efe8d688e88570ba59df7c439faf72c95317a10c984c5ec0043407e9fc" +
+			"9b46487810eac19d2bb40e0a654935f76e7d8861480c5f48419eb33084d4" +
+			"0e1070e5ad542c94f58b49e67dd05b6637a2c67d41451b7e00ba30eff221" +
+			"755d6d427ec634a2b95980d274a89579feccf1c7df3787a9435e588f2496" +
+			"06a93b7ac41c8aaa84b91c95cad9463d4881de7353d95b13bbde4c9da90b" +
+			"f1fe96257309a416407c64368b5564f022c4a493f2a39df1696f45801e42" +
+			"a5",
+	},
+	{
+		key: "2d0035a30d19b9cbc7a27561f3ab474c01115c4499b4adec660ea06ebaa1a14c",
+		tag: "a2c77b55cb0c076d8ea83cfe0e64f293",
+		in: "4e667580ba4f38f64e5cb5566bffb486dcae10cd17acb3754251e837767f" +
+			"16429bba2b832f29ba538f97f3556548d163be25e69f88fff0743150623b" +
+			"e0a1d82af9384ca335927a0e9cacc3dadbdf1e24fa5c81f2602d109e1400" +
+			"33929e409b9a0fa4f2653944edcb8b3ef963ba7f8806196c73bff0ded670" +
+			"c6def5d240c5f3daa121f8d5bec9b2a0b0f1d62d54b013dc742d6bd46325" +
+			"460f692b76d4991f0796820ddebf150c7d33829795784dd2759b334d2706" +
+			"70a7264941be5d99d460d078a9eedc3660cb3176ad302f9365f0bd698e46" +
+			"9f3e63511abc81109995dba17be1abe8bcd28407c7fc8d02c14794bb033e" +
+			"178a94f6dc73719d5bc235f980a16eccb4121ca83b13c4e165931ae4f192" +
+			"4292f8cfdf1c3ed40feb71e13d919b48fa296dddb4d23114a3d86ec10f16" +
+			"f314de4cef813ed24b49f4c7bc44cb8424df1f70e8d77366161c7cdd709e" +
+			"97610aca3a24fb2202ffe15eaaa25d711cb5179212a2c6497a13e5d7c365" +
+			"7bc502b3d2ebde2e57b714dd9bc21e73795f3d35d620613918c4c9aa0e89" +
+			"031481c97a5a4c15ec6abe42d40498c33d71c823bf1d5bb5fee457e2fff0" +
+			"bf777c80c6e3336ab3ce793440e74b336a8f7034f6ea2e4ff5ea4ea7c350" +
+			"65cf2ccd2da1d6df29bde10f4cc0202b5e4cf7ed097da49b970a6db41e5e" +
+			"98f3845b42f46663b1d1ff01da71389a8737ba8f51eac1ef357ba5ac9a80" +
+			"dd2c7f9476111dcd651fc33f4c86dc8658656f3f02a8878bc38ff0d0a1af" +
+			"2e31fb92eaef08c50195490818661feaf90e8b6f5daa1ebedb2cdbc8d5dc" +
+			"16db3505f9611ac46bc37931e02c1fd6aad6e4b7e187d5e6f990fddc9563" +
+			"2b33f55bf68b0db3890b11113ecc839a4fa4de25160e574289aabe4d8fb7" +
+			"9cecf9d2fa75ac8d0195beefbdfe0815f8d7d9751c1280a29b547149ec7c" +
+			"2295f5afa53cfb516158086bf203357eec2a5db71143f996c81555a47f92" +
+			"209719a71570a5553f1ff9b4b41827dd74657b463f36623565f0c9f4d2ee" +
+			"8735d6af56ceb3b3d0ec516b22f0ddafbc24647481f61ab169e2616c91c0" +
+			"e1f6a35436598ed801670e1dba76226cbd0544959ebe70f836c8a7df575c" +
+			"b907d780ed5aa0d6e4e8e0d2f457efe89a777374aa49d4961db96dbb787f" +
+			"021d99231001360d532a70ee1fb94bd6f26524dd4b7556c6d40e08723d7f" +
+			"9905aca66c4743f2bf8b34493bdabcfca617809a867bfe0a4f94c756a6a3" +
+			"dcd04ffc0a3ac671a0afefe0d5d447efcec48c6368998760db6a572676d4" +
+			"29b6d3d6e0c815650447748c4b27541c5447acfb8f7261b6378f3fc0fdd7" +
+			"375eb9d458648c7fe9cd96344f11aca912cc5098e9ee39e0b6794cc1dc2d" +
+			"f1b10f927102705efa20e667b63a91f935c17764650b287f5289d5790766" +
+			"555f31985c5aad94c652ba41fa9c0195d15405f1fcce9e23054a42c8a252" +
+			"da83bf6268782ba44edec5d8f94a20b1830cd1c5894cc6b9b52ad0b12a5e" +
+			"cf3195a32a0b02483ae3b954ac6f3af1e0f334221279d03a72138f3a2cb2" +
+			"1e706427c4d604674dab88d429f28a67be7a996126e077a1dcf8989d90d0" +
+			"8b08f4abb9a546b3c64ecaa287bf3468c59add86365b885f52afe13ed8d2" +
+			"69ea61832a7ecbb96ff3336f58a1eeaa6dde3611f3ff7c2cc8c9b745b0e8" +
+			"b5919914245a49ac192cd77d10deb9a249623f696065a532c20eef9e9b0f" +
+			"e706579566a9eeb14d4e8251a7750e29eaa60f034c1a7a1d51aa03a45fff" +
+			"89acf41080deec5506128b06f003fa46bc4021a82fad6a8052a49744ed69" +
+			"45bd9331b5ae80d873cd042bff079b2b9d8af8065a22c449c32a56dbbe7a" +
+			"80d0f3e30b9167532506915883dce0aa9cb749e4368c595c5bd33b57e36d" +
+			"98cc9bf91cbfa47331d69b5cbe9c92bc66c0fc9ca8717bfc108e1f710333" +
+			"14dba02a28b9aa05890cb01ae9175806c3c4215bd446f6cc96ec5d08982b" +
+			"4f83cd1646160e1d306b3cdec02d251f0901b03e8c3c35464eaa5082586b" +
+			"b55482db97599d513ed8d7a82e32fae302684b7ede058474c1fac7893444" +
+			"16fec93fb982accd162dd956ba2f31a894e9366eca00e6e997fbbf9a2980" +
+			"8b83a139f6432147a717381bb8baa2205715f735c1e0db273cdda6897c9f" +
+			"39bf0d7eb7caf93f657ef4d3fecea28baf69cf36d3cf347081df3114455e" +
+			"b4fe3e49ad3c3f14435e0b39b6c0d16db0fbcfd7ba8da8760d5952c03667" +
+			"251e7a4c3008cfb0904225e55c23b884bb09d26631650460c4240bd5a165" +
+			"b531ee76ba5749b3bc60adad35de519321c1672b47bc35fb59f7792a3495" +
+			"11b2bb3504ba4a28717823a27a1f99ce6970290b26efcf1e7a0399b10eb1" +
+			"0c1299c09b80f4520d00e7908d004d5b6a72a411759cfa9523f6b2912234" +
+			"481b1d8fe4c2365961c0528bd593d42bebb398b5836ae6ca013fe440adbb" +
+			"0090e8ea274f4d8bcae483e3663051a328f7c12870b40e4973a9797a2336" +
+			"3d3c53e1b0d1a9159bfb26158f44734b3c34b571be641bba2db937d4ae1e" +
+			"edc807b95b1c2a7d44804885536316ad38aedf0d83b1519661f2bb5283cb" +
+			"9c50dd61c3753433e988189f26962d1f4befd444257d0b6d5b819d5fd572" +
+			"22c9fdff032e07a4d8686d451e71de4748965309c0a2d7c422ab7cf3d96a" +
+			"8c0a1b0afb229debd1c9421cb828b9f2be96bb9d6b5be7ef8134bd9ccf81" +
+			"51620937d720d83dbdddbfaba8ecd2eab6f1974090efde0ca963e9fdd691" +
+			"ed0cc5e074c5780779222552fa46ddcd951763a32aa3a044ff4a73cbab41" +
+			"dabb3c2c03fcda68303477f0dc26f35bdb5c9bde721fba1a2db732a89629" +
+			"a8de3cfebc3918df1a9d5053d09da5b7316e3285bf62156ca28cb64d343e" +
+			"72445fd66757bf4ab374fe7932a65f3d7fb6e42cb12e5b67ddf8530383a4" +
+			"6c1ee7ec8883e454a467df1aa7e468a6e7035515f473901efca5d46ff358" +
+			"70e0cc2575bbd7f8866c8e73cb157903a1694ff3051424f28de826984dcd" +
+			"065dc3658df144ae3a6d37b88c367e3cf7c58169dfdedda4a2821ce22188" +
+			"40472ff72f0dd1a6b0100555ff188b80f835259a634405e3dad61fc299f9" +
+			"307e27503b2cb7714bf3b636cc64b61d2e374119c8ef8adb21f1516c7fe2" +
+			"38c807818065bf312003c12e02525d69d9629a99e4ac66ad2e792f302cd2" +
+			"a6f5f702dd28040738a084a7052f2c3ed0924c33b7a5d357b7c9a29cebd8" +
+			"621a4bfb7bb34676ff210d59f7f9d4eafb7c5c490c9ea48402af5bb072c4" +
+			"731bdebcbed4e8e08a67931b6d7342d4ef7bc4a75ca1dfbd32ed6027d8fc" +
+			"b71e3f55565c02e06daa8c579b69774889181291c470576a99e11f2c5acf" +
+			"77e091ef65ed243d4287176f7f6ac7aba6908c9ff1fa43b894a499b642ad" +
+			"c01b2fa1c4b58801411941bb448f1f7a04794d2cfe5db1be61f7b86d6eca" +
+			"c547ee51d4c9050f9e9f318dae958c150acc21c878f0c7df6065294eb1d9" +
+			"a278c920838a0db752b080a32e67ac312fa76b589a385f31847196076ed8" +
+			"1021fcc375bfcc8e1361878e2693860eb21ff0595e4eaaf7897f2b79367f" +
+			"7c4f711279bf0c93a97dcb1cd8d87e444ad5f4cb5c1de44e37868c6743f1" +
+			"cd72cec376726f26c8bd4836f9a9f9c68042f95ca6f9d7cde493e531c553" +
+			"8bf7ace6dd768db69ac7b41ce93e8ca27ff20a83ff2148ec5b89e05d8b8f" +
+			"5d78d0fe16b96f6eb8d3b20126a186085c6825df81aa16b3dbf57eabc360" +
+			"71299ccdda60e250c652408d9cd1da94d73c728440ae08fddb901aec0fac" +
+			"1050a778b10f94f84883bee158bc53b1c001807c43a3151fbf581b18dda2" +
+			"527430872834e5c380575c54b7aa50f817cf3249fb943d46933cad32092e" +
+			"bfc575bd31cc744b7405580a5f2eabe27a02eec31e0d7306750adbbb9f08" +
+			"c78cb2d4c738b2274c7310cbf8dd0e59138b6a91b8253ae9512fe3d7367e" +
+			"a965ac44d54a7ed664e5e5c3c6c2d942eac388cd32beffb38f",
+	},
+	{
+		key: "2f29d71d73f7af98f96b34e939e1a21e2789ec6271b878bbebd14d7942d30080",
+		tag: "ec02f4953a9a63ab6f2bfc3501e4fab8",
+		in: "0e0950987f3508239063e26a13727fefcdfd2cea6a903615c64bf12d9ed3" +
+			"887f9b2cf7ccaa196ccc7756b09471475b9daefd4261e69abd23b9faf9c5" +
+			"1fd5d5788bb39d3c068fa6807d30f6201d3f6dfd31715d08b1733440cde1" +
+			"049608d23c4e45c5ed61f863350232f85827e7c292dc5f1eced1cbc912e3" +
+			"f5c420bd945911d3881ede5153d3b2cc85371fff98d2caf97cad6ef59001" +
+			"4017f9690cab08989851c2647e77e81401714a93ed9f938b79f8f54e3133" +
+			"fc2cdef259df2ba0d48f37bf9e43792e3a777214cf4aab6dde6deeb543a8" +
+			"813b71b5974136c1220d6218a252881f0f5677ff5b6aba127f19a5f3c5aa" +
+			"c988543d7839a90a3f947c4e4d5c6ae1ab48dbd40456d1aa65339a4c15eb" +
+			"520e8ff9f965ac4c37735937cf09942e7958f8a6cddee41707423f715903" +
+			"ffe0d15af8c3140d3a736d23be7485fceb9f07c6509f2c506eda4ec9d30c" +
+			"cc133708f48d8828e332808c84a745d337296d871b9794de1c5d06534aaf" +
+			"65587526a84e2521f8b332645e0e72564bb308ecf99b7bc69608474389d1" +
+			"686ffab8c49b7f04dadc28d2ecdd0f508dad2135843304e378b3bc7a4f25" +
+			"7fa4316be956e0a021edb8045f39fa9f002087f067199bd6001acaadd261" +
+			"4bf6aefd3f098f92a959685f24bb2206c347359d9c6adc6847117bb434ac" +
+			"6c40ec618f6ae8b75a5e2e4d44c332b7b06c8b4d521493b9b0bde8894209" +
+			"717a24b320214297b62dec741cea018ea681c9b56702068528b3726953e8" +
+			"c5e4ccd5029e4183e772d9834a56a88d45bf87603dfda40e03f7e894766a" +
+			"7623ab4dcc0dfc3086d17566945069173935916f772e2a5f8e1547348f28" +
+			"782400fc069ac0e2b94242e9e0f1ba2d0e76898f9b986540e61ea64d7f69" +
+			"1006b86ce61565da75eb16a8b4c5865ca4eebdde2190e354734bda94fe7e" +
+			"12ff47dcb5d5e6ad93cfadcc491cb350b09ffe391a157e14b65e3a211b5d" +
+			"4e447c3ff95571dbab33a83126d68dfddf9383b4359d4103ca64af1e6963" +
+			"d09e17eb944aa71e76711dca33168586bfc44ebe9fdc55497d83f238c66d" +
+			"bcb16063bc85635f0f1a6280563bca49ef971db96a41b6ac5e0642643262" +
+			"61eb4662f3d6ad4cac826db895de22c9b8aa35e6464a7f44e1ae7238e355" +
+			"068d68754ffcca76c50b7ce7ef9bfebac9eeab32c87d059cc7ef2adb5d57" +
+			"c7419adb394eef48441952253e8391e555730e29789d6293c3696f441449" +
+			"0aebe2bbe541e191a6652ffbec1192f0f9395b7ea370aefc1f1cc8438035" +
+			"d7681f12f1e11d6e334da188b10c302fc0f4bcf1de448090510a8f1d5683" +
+			"0c943a3c388b33a038c26741a4cf3487313f755fe7a28e25e44b5383c5f4" +
+			"cd6ef34d7dd73462226281899dc3f2e69809a0150f694673f31addc89888" +
+			"072a7d4ecd63d6b90540f9522ec05829a7f17d48728345ad808fb0203883" +
+			"3cbd018d612992a88df944b8e34a70920b3f26cda2e8bb16c3aa38b12b33" +
+			"b395c9ba5e809f60ff05f087112151af1b5987403cff8bb2dce79093f431" +
+			"2c744f911a6f3091e4f9ef9375c4dce4c241d2f6024a1797321851ca316c" +
+			"4e460fc060e7839deaff8ab5e8bf682c0f21ab6952eb793cffe690db911f" +
+			"50b11f56ea352942c43bfff51d4360882754faeb7cf28b6b32bf7fc9ca71" +
+			"fbfe1d72be05b8bac9ba513d731e2c9d13d6f2f10eb926edaaf0e3996656" +
+			"da8718a8e103c59326529e91ebac6ed52657c9690ccbf81028cd9fb189ec" +
+			"4de94fc0771e53302c8d9082835a68780cccd772660a110a1b40c57bef3a" +
+			"c1d69428aea549ed17663a96895a66a3bb5ff6ff61dc64908df49b760caf" +
+			"a5aff05e2766a418dbaa1e7d189a9edd55a04fee8c9d6e506d299abc36a9" +
+			"d67be035fea5d220f41d081af67615fe627c4dd04bd8659c7fa4f57f35d0" +
+			"db40d9684aa178d7483ed5d86f04eaea412e0ea05a4698377dbff4fc3a39" +
+			"1f6ce0cb833d3118d6c69319b511cce65fdc74928e270da0c537f8201eff" +
+			"77416155d4a39c7ad38c22cdbf7d2b7ff7d85383c178a835ec604c3f9ee3" +
+			"7399f7dd826e34f1a35ab75da44ba56f86097ddc0f3658ef5bd65a24f4de" +
+			"4255d0b03411a9d7f0ddc29e33cb865da23393471aa94e6c9e72e789206d" +
+			"3ba118aecd39727068f528f01b25fae2280d70033e4ee46b41b864bb922e" +
+			"001d8bf46d6fbaa5a594e926f45eb3a4d2f074506d7834b606f43c89699a" +
+			"6db00b374658d9333700894d440a712a1f25f5538f9e7c8ee57ae7e612df" +
+			"13292c8ba9dbede4fb77cc6c8944aaef59ea6ad3b36db398f4bb0f82d40b" +
+			"44879835f224d6e05992b1b8a68dd58c3dbda2fd73786492ee48c7a25f87" +
+			"264b766930fe9427487504fad17f8d230934f044e49ba219f26ead728856" +
+			"cb30eecc33a3946d3b1b781061f2458c7c46f6d96f3e06f369f97be91835" +
+			"f23b38347d1e381ad5be4419275772c2abd549522a0203c1ee9c96faefe1" +
+			"df413c4b7b2624417890e0716854b7092b3b3b368cb674035d3e6bab2357" +
+			"e7c262b606f7141b6dad2f6145ebc1deb7597814719784f3c17848a90ffb" +
+			"cb0289e2f3cc7da12442b837c4e47f468bca3eb4e944a31c48562c2f144e" +
+			"9e920ab5e4cf90a14ccadbae29af13db38cda911e3c8f6f525e6722809b5" +
+			"31a4de1926ab12f643d25af87eb8610df59eded6ec278242247dc69a4213" +
+			"13f7c2b26ae7a917c1bdaf66c56876e9104d40b59e6ca1431ddb77fc89f3" +
+			"14b46a154cf127688564a4f9e120d7b5816cd24a6e095dc8ab8b43bc3639" +
+			"329719f0e0f723e2f5136d82638e2249e648ebca67cf0306741e9e8d45cb" +
+			"903bca85485c4007397c88a1ce07266f4f611b96b7e0ace3074247a7dfb1" +
+			"cdbbdd66e25e172fd2bda74abde7f3b4cb5cc7ee7859f053b2f04f9de03b" +
+			"a8e96264117f502087c3ddbee8d850bf3618b4de90f7b3e562dfa57e4426" +
+			"5357236e35e71d1669226d63bca50b1b944ac07a1f794e73e80985689b25" +
+			"f18fc709367d63b8639d71865cee667536040be827145c08cf3e57a66678" +
+			"4c81115706a146eccadc7aa1a9f074b47e95bcba7db8108a13279077bef2" +
+			"64699fb87e5abf5b05ff3879d7c7c5169c7cae817c13f0859d4e9c05db0f" +
+			"74c045ecc30a51e515feea627da387ff780719395b5b9ad93179b16fad10" +
+			"5856049169dcebd43a7f39c549762405f807378e854b1654a1179d895ef0" +
+			"85aafc72c7fe1e0e1cd3abf8e20935e331145bbcece4f17ad24ebb6c64ea" +
+			"73bd98a7494c134859206c9422f7c4a057db0ae0770c4bcb08c1a6b9ca4b" +
+			"7dd8c1cdb3e4977c7ce6c1e79b9d6ad98e27d2759b53cee73ec037a8b686" +
+			"f1ff78eb8421f41c74ce9c62a90d38b75159ec925f232e0db71362f31e29" +
+			"4336f5580a34b26c5a01ee3454cba227c7f400f6889a319d7121dcea27b9" +
+			"584f33ac796d48a9a24cc5b6799ee12f10725fbc10d7cf83e4b87d9c444b" +
+			"f43e2f5ee49d8f3b531ebb58fed4234cb8bcab1b8b18bf50956506baae8b" +
+			"c1b7492250f3adf64294310387f1d4bcac12652895d4f2dce26f380733ce" +
+			"0b5820e9fcd8512a1585a49940a32fc8875ac3c9542a4270602e5e97e720" +
+			"90ed71b51badb775340429fdbe45b887fb9ee61cf9e091c06092cf0a2129" +
+			"b26572574c46910cb458bca7c63eddd29d89753d57e568323e380065794d" +
+			"3fa1ffb874543f5b0ddc702b087e91e22604d9600d37fa0dd90d7acb2458" +
+			"4cd408a4e66bb781dde5f39efda6a8fc26be0d08ffdf851e422ab1500c28" +
+			"bf6b4c85bdfa94e8aef5cda22870c39ad49c3c6acdbb3b0d58cd05424c65" +
+			"20740b5c2bce4336545eda12716317df58e6fb764fcb3004f5248c5ccd84" +
+			"f63abdc0dd2a64e447c0de4da4a1082a729d8ebe14810d396933085cde18" +
+			"318278481fdb9a748b637cacb491f5234bfe16b53a35da6677336baeedb7" +
+			"4a28c19a412e7812dace251446d40ec07afd63854c3dffbd5c0f6a9a3cac" +
+			"ee3bab07fba94800fd1fa0fe44f5f2ecb2b4a188cd02b8a2df0728347c50" +
+			"7d0cc58fcd5d54dffdbda11dd1bcc59758396ed8db77498fbe13238d3d8a" +
+			"0040194dfe66811542ddaa658094a9580d4e4b4e29",
+	},
+	{
+		key: "1285f117bd90b70ef078ae62f37d2218419e894b7d334759ddb2d88833b287b5",
+		tag: "429b2b39195a10357043c9601590a277",
+		in: "00ef065a1adb4ce7108b497813ccc748933fa8442689a7cb8dc7c1ffdbf6" +
+			"c09adfe05ca2cc5ec3acb7493f3497ee8f9cd9bb8a4b332c18e33f78114a" +
+			"c8f9a72ddb9f13494e934ad711818909831013ba195b53f5e9e5b4689399" +
+			"6d0b669f3860958a32b85a21009d47fddbc8697b7c9b92dc75d5060eb4fb" +
+			"40aed7a1dbe69dbbeb6296f5467ea2426cd17d323671fa408855bc53e5c2" +
+			"d111203ae38cecac7719c0bd7f21f6bd6a1588187b3b513983627b80ac0b" +
+			"300b7fa038af1cc8512403ac2cea6e406595202ec3e74014d94cf8780ed0" +
+			"33c570e887ca7fb35ee4768202aa52427d02c24e63f7f2cede95ca9909e9" +
+			"dfa86246a27db757750667c198c9aff4ce348f7ac51864b36ef5695df713" +
+			"d17b8f561a972d0136bd9ee9aa16079c2ab5d29ac9ab472255ade05dc49c" +
+			"b966e0c1c04258ef9ec59ded01f402d9fdcd9a2020a2038a8c78892ca218" +
+			"30136069485527069132959dab2b81c73ca590fde2a7ecff761d95a54d63" +
+			"a2664aa5a6deec163e46b5225bc98976a4f363063b0f42e29f792d138af8" +
+			"eae68d3854b5c1985d5cd1c9f49f529b0b4d2c936887b5b92cdebacef992" +
+			"c35e0b7bbd52114aff8c6b261852e28e451b02099814f809b0289cba0586" +
+			"04a363e3f969aad3d982f645ec4c549f943fb360fb8fa0d5a597bf89842f" +
+			"8ced6014a5b2590ef71524a7ad50fe0ef0e2f81b6e26b99f9ebbc8036549" +
+			"f7eacbf6ab884710c6406ff59788e03ede35c30d4781ad5af171e0623e8f" +
+			"cf5344d71165f0475e256e9159040f702b359a2963116ed135dd6c1d111d" +
+			"2a1e33e15c178ca4f02c5fb15593c50cf9a8a492f01e04778dbb81d26c99" +
+			"0c58cf50a9bcf4fe38fbfc0fc0685d8bd422a773c7bce649f7a86c59118e" +
+			"f5f857b2c72508cd1ef05e1a0c0b7ab4687fdd57437092eb49bf41a9ae8b" +
+			"bd98272ea2f8ee2515ff267fa6ae892c266a7effe61ed54984924aefc461" +
+			"6cf483dec024ad666bc797beaa429a742d1b8806f67d451b6d3a85b4d474" +
+			"003cfe9e9dd906df47da5559c41f15afabecc3e6af279cca0f2a200eb2e8" +
+			"31437e034d457fc880f60f5ae635690bce82bf6d1ad6b4f5344ec042bf25" +
+			"7d010273c861e3ac516e9ee2bab3a255f570baa32298467bf704bf6d9076" +
+			"a4c0b08a528a05cd1fcbdf51f3885fbaba7891a144fc058919903b269b4a" +
+			"29f43926eda32c38853b814a7d528156c223748d674d8f7f5448350f011b" +
+			"bfab1511001b8014e20fee37ccd4a0456f638c197c86dc116b34f955c0b7" +
+			"dee10bac5ea0c2fec8a780ac05098b51b902ca6afff4db3c6fb4f761df79" +
+			"b2039dc5f16d9402442a6fcf6c4297769e6c36824d908beba8e584ea0b3a" +
+			"91b9017baeefac651d0307bd89f517789236c0693c65a5a20f244d39684c" +
+			"eb810cd2ffd3c78fe9285d2eb9f55d133b86113efb8dffcbc6d258e84c38" +
+			"2dd8f4d7d63b65672516d9bfcc3310a79ce244b60d380128d529487f99b7" +
+			"d532d5f5c28fad8b9a071fd2fab8fd98f6d7ed9dadbd2fc4396476eba6e2" +
+			"1a1b1cc594a31fbd3418d98e4aa736cab285a2786fbbd4650e49f9b080ed" +
+			"3fda34941c28d25545395e1408fc3e60730d0696061f821a4d24123cadf2" +
+			"3af3d37ba7ce1ba3cde1368d468f136df82c02f9be9210022192aa02117a" +
+			"ef5ff70bcfeffd47bc37b920826a4d3db001f956939abc0df520f3ec1613" +
+			"ba1c4b3385cad97e42bfd15a3150711fe86ba4562f17780cee1cdf198615" +
+			"ca06270db84986f33e1d53d552b0da82397c496a23c7a78ca7641a908e71" +
+			"89249cc657c0431f1e09ae0213f28a27e6267e9d17b5bba0ea4f3c21f266" +
+			"fe538e215ec62f85517ae6bd87799ac5ce68453f09cbbc50d6e2a168f0cf" +
+			"7166ad50cb65b6c76406c326573c00e04a3186251c6181933828c58f4198" +
+			"f8208c4484805639b0d428fd05b57e4356239638f458a84000c7a7a8de62" +
+			"ec25b54d1e39d2579ec9c512fec475f243576f35efc02a1cd6b0478e2dc8" +
+			"be5f17aa4e3849cd42e76fbffe6e7d6f912d6edf80f718f94a7e48e1fc10" +
+			"6cac29627d9d4b82f05a30cd7c739f7f3ef7ea368d22612f189da450e274" +
+			"de7b61c6361521e684d639be5af4cb11fefa5fce6f8a5065c90873e504c1" +
+			"2c940571ea7bd7e9221129b83039d2edb069e8b5bb68567d8fcae34c6ee0" +
+			"cb94474d8b056cc3c7403873f2fe6db3b567a44e702e4f4813b2a264231b" +
+			"0a998207b41916715ef94e5eec281589d0a711f8e74be32bc60f43d693de" +
+			"77f21d5f7eef892abe87725f3d2b01d9ddb6dee15f40735a8fb67766dbcd" +
+			"020a93b8eef4361dc3a891d521551f65dbe6e3f68c60819b0a540b0991c6" +
+			"4449d207cf5b1c198c17ad6caf3adc628d09fa0baae7a696d84e1879577c" +
+			"ffe9b3f62669d4ea5ebab6364f08c66d170ee4a94d61fb77d60b33dd6b60" +
+			"650f034c5c9879243d5c16f853dd7a89885a9047a341b076912d47872b3b" +
+			"3de49edf7451b435698ac4e182d16c339be83e18531a34aebad36c5c7c93" +
+			"aaf121cf99ff92d3844d40740fe001eeca9ee71300d826bc3cfc87a29d39" +
+			"ea108a3cf259657ec4b967fbb534e7513ef3a96bffb35abc5ce0e890696e" +
+			"54fab515af3d2c0be6e003747504e486c0ec6e30fa4ca79d6596ae0425f3" +
+			"396e40fd37432e52c74f812250dad603b3502f97ada48a26e39fd4d44584" +
+			"6591bfa5ffb3770d95d3dbd49e9c3a38c6305796b8f7d79bd0845170925d" +
+			"575774445299bdf9d3f8ad3dc2dc5cfd3ef0293b84d6e11370851af05ebf" +
+			"b3510a22edd930797dcb76b759a9b5a77ed8dd5130e79ff5ac44b01901bb" +
+			"79603cecf674202bc5d84076ff41b3c806454ce80cb9e5fa9db77294d20e" +
+			"6d3008ae3017aba712862ecd4b32daafef1b8cc8b19ee8f8bc3835e2372b" +
+			"5cec66222ad5ea9df753c033508ec43c8b5995e88c36c13ea3465c8bc462" +
+			"ae0a659d9767db34499e9d01fb1588410257d6f588b3fdb766a66bce28b5" +
+			"e0880f8cf988a2e5eb5bf80cd7d83192b7392fbb2e3a07d51aea2b6bfac0" +
+			"d74d304f56d5af3598a0712cb09c04c5dc14194eca8e1b9b29f88344c0ea" +
+			"55638c0f8ebb70b6242b797fe2525fa1bde76293dbc0a66ab4715e6f9b11" +
+			"f7ecd8f35a20ee4ff3552caf01bb307e257ec0576023d624d6094d43d25a" +
+			"aadfce939a6808f8baacb2109c3de50a1cfada9e384cdba3e97d2c9025a3" +
+			"2377bb195fce68c5569d2d1267e1bc68fcd925ddb4acf567fb29ea80517a" +
+			"7e4056fb014cdee597333ac2408157ff60cfa1afdc363a11fd4883308cab" +
+			"d9a8fe56c2b41c95eaef854f20bf5941ed23156d86de3bd413465a3bc74d" +
+			"5acffcd15722879849c261c1bbe987f89a1f00b3069453841b7da667d566" +
+			"e41fd894d94de44c23fed08d9bdffb723aa8449bf236261240d865efd7b1" +
+			"74a4460e5004ff77f4196d1d421227dff7c78f1726df7b5eebddb4bb5f57" +
+			"5ade25296dda2e71ab87ea2b44ef2ce8742a7ad5c1e7a40e097eb336561e" +
+			"865515f7ee0efbe01d5a928f208f7c9f2f58974d1c11af0e737c673dc446" +
+			"1795da9757010cefc6e7f2784658717938735ed8cbcbd7981a1bb8f31cab" +
+			"b901c87a3218dd1195c59f64d0bc3ce8b72580fe38e6dbf1181e0090e5c6" +
+			"d162df9f31cc52fa6a8ac61897e9b4b3cb0ca2bfb38a38d9b78e46d775d5" +
+			"7645d2d6da16bda8edd8675e2ba121f7f85400cf7cacb9ffcdfae583fb93" +
+			"753d07985a00afc3a4e26c9939a5116d9b61196502f5d774ab4c7fb6cfa6" +
+			"01bcfddcfabfcd28055e858d7d3c19feb6bd7c02565add3a3af61bfba8b6" +
+			"f4b52c072a8613e878368318383143059a98a85ba521f781a8983c2486ba" +
+			"b83f5b91fce02acee0be8d0dda7489975f0506c8f363b5adc48ba971adeb" +
+			"4e1c830b5f264ed42da36d2b5ce2fdab1e63333b1061ec5a44ec1b6e99da" +
+			"0f25e7f7250e788fe3f1b8e64467d3d709aeb7360720f854afe38e190cc0" +
+			"925c6cbd77fbfccc07d8beeb0ce68e47442fadaf13b53c30a03ce317cf79" +
+			"dc9155ddf96814583695f15c970fd0b6cea0b04b1825eb26e65ea9351bf2" +
+			"f7a841ddaa8c9f8e885b7c30b9985bac23d3ce777b",
+	},
+	{
+		key: "491ebd0dddefc9f0117176772f9bab61b92a1f1de13796176091c56d1e53dfbe",
+		tag: "fbd3f884a3dc2a8be06ce03883282e1e",
+		in: "953b9a40789b206fb507ec2c5e9c88ca1baf25ad24c11a62f664db1da8bf" +
+			"dbe9b54f8e93b0bfb4adb12f8873096b8960fd91eb92a8ddb53232ac9141" +
+			"57caced33424cff943a8db129049af7e7b733afbec6637d8ee4f39d063e2" +
+			"be241cca6a339e48d72372efabceac57220692c40856532d95529adfae87" +
+			"a71c72f30244126d01a875375ad8836ef8db929bc81027935042a05c346f" +
+			"bc94dcc057db015e55c56064d2b11154596b813ee64b73bcac05d2688bf6" +
+			"f1fbb0cf3f8307b3df44c3e2dd1d226a4d0e9dc5f7482bada9611970f887" +
+			"f656dcb19ce1f8c5c86f4cbd1e4f49b18f170ecfd184028e769e79d7424f" +
+			"d01cb315897c21111f53f4d41c3b71402eea695272cb5b4e5f33abb9df50" +
+			"cbdaa55ed629d3ed7d93b43e550295502db1f2ed884afc320518e88be4c6" +
+			"b62a13f8d3636ba091d07dbc6c20c7e7fda016c05b2fadcfc9ea32f4ee2c" +
+			"4893de78ad8a1771aacf6efdbd8fb1f6ee9b0572ced3edc6313185b5d398" +
+			"88ce77950aa4c5201a256e3ae3e74f05b70faada14124b35b105a70e7769" +
+			"7184576b69708eaabd36e0ba885fc6bafd5738a67307a1181792333cddfd" +
+			"a4ef19c88497c82fccff05a8f9f732fc7505f0467a14e135288ee018aef3" +
+			"d0412f6b0760573d8ee4ab455d2789b4d22a42eebdf60616fe403627cfca" +
+			"fea672bd0a49e8e7b80e7b7b8feebce3381f2fc16819a8996a99ea230c3a" +
+			"84b510cf2e0d914610d646a2f45a14268ec1d6fca03d0aea5c9ae1c8d519" +
+			"b0e8b0f6fb8ad176b5d6aa620b253cc492b5e5645353fbd9b6c02bea48f0" +
+			"286e2c669782b5ffefa4d8f3f1037151026d9cca78e7808dfbe61df29e82" +
+			"951d7154f3c97606cd1e99300012578ea6a776dcef0811338b56606b51a6" +
+			"9893fe68f762af6c9c26066b1d503e64877d8cd988b443af66a36af8bdfa" +
+			"41b4dfb3721d1d81895884755b9c52527030afdfaecd66d4638fab1d1786" +
+			"3d5517ef7ee7d081b5555d24991810f1edde30930fd392f817cfe632b4ca" +
+			"6fb0460c36bde4a5620b9c369bf51c7d870c43998b8171a553d2f643fe8a" +
+			"58aabfce8cf7363ea978ff4d53f58284db822ca95b80306ec02a64d26a29" +
+			"c98520f1924c70d161682c54d08a2c48f54bb72980a8cf5babd0aaf0fd72" +
+			"7d5b1b9d9b731dc49bad228fe83f7347750e277a4fbd526983c206e075d6" +
+			"a03d68957b3e925a71bc1ea7304c77660d112a5d19fd21a785d4a8d7f2eb" +
+			"dc4183376d8125341eb28b2df5be0b4e04bbf95c47d2fe2aed939619cb97" +
+			"79548b752f57b723cf8295dfce69c9b7486b75a4e900f91926636f3fc78f" +
+			"7b7720a5151abdf5868fecf1e1a1d830cd6a4c5e3cd739da4432cf1fe2af" +
+			"a1090d6a1eeb32e7236ecfddb9d07b97220ab8e23edcc93d91abc11b0c30" +
+			"460d2027869d1c2487070cf60b85ad0b8bc5df566f6fdb0e58fd044da530" +
+			"6d277e564ca6cbfa820ca73fb6201b240a5a94c4ecd11d466cdc44046a66" +
+			"32478221bfa69b3a2cebd16baa302a573c90895d7f4cab453b11e3a4d8bb" +
+			"b5a9bf264781ce5b9796e3c47d0fa57f46b923889af4d073270a360dae8d" +
+			"51d85ea916f14787c6500d2d906ccaaa92d20d93edd09139f79bfeb5fcd9" +
+			"8c1cdbcbe9f2587e9c9094e3c4a32ab9ba56f400b929e80c0551f953896b" +
+			"e8eda6ecf22e6d4a541957dec21d6a9cf388ff0ba58169ab934902892a58" +
+			"86e1126b16118e965a271495ffa339c49466209ed3875b568a4290b7b949" +
+			"69d0465744a3c2a75c599c3a04ab1a3fd09125fe8f45724b2f48c7822b9f" +
+			"ef95af4b758ae66a8b6646df7a0a1aabe2a24c052fd6d30561cae0389263" +
+			"e3388c4c1effe431a04356c334aac64f36593544885c4b7295b57dc39638" +
+			"b665b22dcbf7dd6da867615de38c6a575cc66391135d47f8e1f0c73c6129" +
+			"17ada4099723933a758d83311b384364263cad5fe14bdd7c825d9601c400" +
+			"3537a5aca7f9da4710c132ce8b0f1464cee625633ef57f507739a0ab1cd2" +
+			"21ae634d4d0b3ff07e9ecb1baaef0a82a97279d46543a0464855cd62c07d" +
+			"5e890265612906a9eac88bec07b1dea5f67054c31ae40f8c673296cc5df7" +
+			"f0dd8cc9e643b44fd90dc2d1e870ad8acdbe165237642fd04c00965837cf" +
+			"bd2344ae830887a5719a3c16dc8ec08bd9131d055bfb959b64ff4cb638a1" +
+			"002a4fe02e369871cc4e3ffda17dd85343e679fab43e11970e60198b424b" +
+			"676ab17fb0dee10cc9c2e92b32b68d5b05b7a559176f822850c0557ed98b" +
+			"7454916e32af549a0027db95f02b88cfc5e7e05f28f53757dd97cc0f0594" +
+			"212f8801e58043cb17b040413c226dfce2104a172d218caa4353890de17d" +
+			"be1f53af6ceda24b8781801516cc51de9ca459e469b3c322be13d8c9541f" +
+			"755c518ca41a0ed42e44b9f87faa2a968b0292216e9f3d3e8987282103e5" +
+			"016fe9f7681496e1e8d663eb2d8bc30b41d735465527f19e336a98d2dc54" +
+			"d7c020bfab30fe6c62cbae7d09f84af69bc2c51a1839ffba15015d381ba0" +
+			"a44a3758771c4f18d13827f518f30bb74f4bff29a87d4b9e949f1063f63f" +
+			"662721cfd64ffe1dab3761852387f78fa83fb48ae2c75fc567475b673da6" +
+			"fa8f53770b6e5a3c9fad951ec099c6bc1e72d1c489e1ae620e7f12ddc29f" +
+			"ed65f29c65cef75014b999d739e2e6e015f928a30f2fee3f2e59bf65b54d" +
+			"89948bf2bfde98b076e5460643952befd02fc1b0f472a8b75195c53ea296" +
+			"6403b9028db529cd04b97231bac3068855fa211f4d976a88bc27a0088f04" +
+			"576e2487ac0467992066ef7667ca8429faee92db38003728e5c219c751f6" +
+			"6f011b5d679fdd957f4575a0cfb6b54693a9624f2c7e66c578f5f0367005" +
+			"c66addd1e3ab7ea1ac404e357cbdab9438b9b4f80b3a6761b864b006f1df" +
+			"689ae4c0434b06b686d5353d3e421b57381ea24fdcf6199195ccdb3d5cf4" +
+			"623a6bb1f9eba9b22fa15395f65f8093b5f90455061c1cbf8128b44a31e3" +
+			"910862a59e187aa7f4d22e0317ae6c177cef24eebc44171f70c25efac73b" +
+			"38ada0cba0b74f72d1c171277a734819c1111ebe46d5db20a6ff20e2c1a9" +
+			"a57edae95a3c1f80ddf2b12c86d3df0078a7bf68695b16ccf92053c727a4" +
+			"80586b8d87d0d1772e456fde0c20a7927f351a641bff5f22f9ee2217b6a2" +
+			"d0983c8102d7d5356dea60a19e105ce366b9d000987c8c33396569f97c56" +
+			"2d0fc0bc5859779aa10efd1f8df0909c307a9110083cc6d9748456c9bddf" +
+			"16dccee52b7974867cec718bb0b76b3353379a621257094277a30148ac38" +
+			"e5cf67ed7cc9c1bae12dbdeb99d7d880ce98e17f0dc93c5330d1824a3c9e" +
+			"ffd86f89e15b59a4bee5a48d4f674766896e187abaa39917b83f8d2f3265" +
+			"bbe7aac44c9f8d92f775fe6493e85ab44e6e28f79f28eff156c21e1abdae" +
+			"d10a291b88c4020b1ae8be001080870847a852d073e82bfc751028ac62d5" +
+			"6aeac1b18f2cff1c0c7d336bf08f8cd5099d9d3b28f9e16077e9caabab49" +
+			"f2d234616a7522a6bde1a3b3c608df4cc74a6c633d4c8068138abda8d26b" +
+			"4ca70f95d152888fb32bdee5dfad8ff4a5b002a0a327c873656db8d6fdd8" +
+			"ed882e47ce8e47c729e1292db9122ce2e9fa275f9bb986eb7e0a1dccb7cf" +
+			"abd0449c92fd35e2aedc4aa89caf53bcd28170cae85e93f93988e723a896" +
+			"10cefb4edb6fa545835fba3107e21dceb272c5a32da26fa77df070f41d7c" +
+			"ad1d68b836199ff0f1221e36b9b976b5e69bed54b5bfec67fe9cbb383484" +
+			"696265204797634594bc335150daea92dbc1004f613b4c27bf5c699debf9" +
+			"4365041b5a894701da68a93bcb61f4e546c553fe61f14ab0322b45915da6" +
+			"ecacaa093b0071f2516ca8c3fef2f1e3c403993d734403c47bfe5f4379e9" +
+			"cb5b613fde3c0d880cecef4101aad8b8b1c60a92ac5185f6c243fdf1711b" +
+			"0b56f0fd8e5ed6cc0f99da888e4f156455a0f0eb365b8964347eedd15d80" +
+			"2f297977af667ed1376dfcc610f5152421b97afaaf16f9db57a435328595" +
+			"b9aa00b5ed9ff106c66970fafef379f4d2f98f2c5984ea05aad64651fbf7" +
+			"7968c8cbc4e959859b85302a88a3c2faed37765f3f6ced59d8feb6c72e71" +
+			"f9d4497d98bccf95fcb650f29131e1df1bf06a5443f8af844aa1a7b5a68e" +
+			"bb250c7de3a65ae9b1086cf83f832050e55030d0f67c6a54ea2a1dbe18e2" +
+			"8a96c9e0dea2966997bfc5c5afd4244e3c8477c4f5e8bee8fc8ca9a5cde4" +
+			"d9c5a2c7f3d2e811b1de7ce4279229319e432674c609b4c8b70dc6172e9e" +
+			"653fe1969bbc2cb3685e64fd81d96d33",
+	},
+	{
+		key: "b41db44465a0f0d70093f0303bbd7776017bca8461c92116595ae89f1da1e95f",
+		tag: "d8a111a09db22b841fa28367ce35438b",
+		in: "b074b0984fb83749586881e8ec2c5ce9e086cfb2aad17b42b2429d4cf43a" +
+			"0400fd15352d182e6c51e9338da892f886f460d40bd178d81c52e9ab9c1c" +
+			"bdd812594e6fe7a9bb7fb729c11328d3288604097600a0c151fa3d9e4268" +
+			"de75866558e9f47d8dd331994bf69f826fd4a6cb475ae5e18365f59a477a" +
+			"dde7fbcf7e40b4e3dee020a115830b86f0faae561751e9b596c07491c42d" +
+			"e02fc979e69071113953729d7b99f1867116d058a90f1b8c0f9ba12c6322" +
+			"4ebd1b563a87734f5d6e2d4e6715d5f0213e33316500cc4b23784f78a9bf" +
+			"13fdf99bfe149cf47aeaaeb9df1cee140c3c1264fe89bcde8acda6bde16c" +
+			"e3d770ba51950b67ad2c5232ae0cff048ddfda8540cf18e673582dc96987" +
+			"4b127f655e7d4e08859f2c6b95403cd5b4e2c21f72bb872e49e592306286" +
+			"48ba1b16fc9637709636b198f9a297aec364d4c3bc869dcad32b1830e434" +
+			"b556b429136f0012a0a0b6fb3797bc8668014b010ea51674ef8865348dcc" +
+			"197672047fcf72e6b6910a0e32a4f110d85e28db0e338d9cfdec715a8800" +
+			"b4f007a7951d09e41620815848c89f8768344c50bd522c46f64ac6c98e53" +
+			"92176651961c7a70b62f3d1819bfda674e2ecd3167415edc4b97419e8ae4" +
+			"9974b56cd8d52e1d05b82610b59606a750b34844ca33bfc9b21fb970738d" +
+			"b66f48928df79cf67730a30b0b612f8c15c22892120548ab460a6b9bb3ac" +
+			"e30554c86c9681c797821a1b1ce91d0e87fe90ad4097c974cfbdfd5c4c24" +
+			"a5f808f388e1b1473e858f48a387614501c8c39d6973ded69b1764663cd5" +
+			"166be02b596a49e392d637e3d8afc91323f7450318b79d5488c040e346cf" +
+			"0cee512044514b570aa66bb98d639a9ee23a7cebe28474592623d082873b" +
+			"73efb3eaa4721fc4761e15a390497cb13cce181107e8b1a0186b9e47a5a4" +
+			"b67a5be3cd88a43d341ef63f10af6970aaf56035db938655020809033a92" +
+			"8d4fe6d2f5424fbde2fe82adfd991d388edf293cb4e3eb68d876f225a5f1" +
+			"58208bcb1aaefcbc28d6763d267406aa8d6ecb413d18cff7a318ba031ba6" +
+			"0ac4560748c248de64eec56dd4540124b38581604f502d94a2004f9eb1d6" +
+			"edb009e16af6c6d3ccbea79b10743da98aee7ace407a90c6cfdde694f36b" +
+			"e0271e722618a457be68619b980754795f4ac95ebf4f1820b85ca8e3fbff" +
+			"a2430f8e01ab422d7140751f7741f2c921400dac404b04e049736738a87b" +
+			"6f49bd54b1b447b922c473831a65f224ab84fc96e4551a0333bc6187e15c" +
+			"c0f0ad628068bcd7c043bd1e3036ec01e7fdc3d157476149917baafaced0" +
+			"15d09fafb92181a0ec65b00c9c13631e65de184377416e04d3d93b847e0e" +
+			"286c1d88245d4d550d30d4fbfcb416ff26a39a94275631c2deafc7cb6780" +
+			"f149e4d0e9c4515b708fcd62be5252485407a6ceeb9247de34e0266ef384" +
+			"976f6d31284c97468b3b03e951d87a5a00836ea303a266147a79ff3431b4" +
+			"b382e86c74d92661e0f65e266b7d569c03994b667a8137f3080eda2ff542" +
+			"0f0b52b427558dc26932a22a615c9e6b1834a251c6b68fdfc0bbe0e8781e" +
+			"36adf669f2d78bd23509ef7e086634e526258e8d11a1e0be0a678ac09c7b" +
+			"b4e3c5758504011e701dc85997fe2a3e40c7af83f032bdbe7adc10ef1e4a" +
+			"666946c2bf31dd8e3a383211c9684d5302f89dafcf77976d5a02c14e2462" +
+			"09d2d99918e82402cb0eacaa12032ad8316315af1b3d3bd5058f7c935d35" +
+			"ef0d4e71373958fd5e4140a9a586d89c53e4144c00148a4706a524896eb0" +
+			"5b1479a0de5d3f57be46b3f5fa4e49bffe027c81a33e37abc01a4cafe08b" +
+			"8e21fa86b42be52d75d6407e6cdf399de7aedb9b61a6917b2677b211c979" +
+			"33536664c637a57ce2234e3319fe8b4a77d7285ae6347464dfd0aab3e6f1" +
+			"178e0029686770d3b0dd541490b097f001e95f27efe8eb16e4747937d643" +
+			"cdefd49e586ecad541270cedc3064bdb7c79f086bf1fa8c666304d977a15" +
+			"54ae268881e17d8bc3fe51fa9969f7e560e3d3e050424febec0998b35f2a" +
+			"7378b2c3e384cbfc80c4987734d76c78224cb81cc5376f88f0ceda28aa50" +
+			"44e956537c3ee209071d84a66173384e0aa466d989759fb1f2f17fe627a0" +
+			"ffeaae7c5a3884b237f5151278a07117c2e833f1815c7e0e0b1611f25058" +
+			"ca338d21deb1a571faf1d0486667cb7c58e2814c3722d24fb77ce1b7e018" +
+			"2ae5746442b5ad00208b17c0a68bab4df8a8f36edead4fbe79b4c9220dd6" +
+			"acea6d23c7caaf6ce7cabeeca677a1c764d610ea6c7e994d6a9c88f57fda" +
+			"ef160b251e7595578ea2cc1441d480c14b8b6945e76a001891b1f214979b" +
+			"c52ec15e9480d706a40cb6e3b259ee99a9e84e63a738f1b52cf71c8ecb04" +
+			"fc833c2c680bfed587aa1541e5ffe8bbd7b21302bbf745011e559f94f952" +
+			"8b7fad8a37f6d855306a5be22725859cc950bcc334179d49564af3b9c78c" +
+			"e1de59a9cb45086a33856ba7195c17cef573950155bea73ed16645768bf0" +
+			"a5cefce78ba3ff98a54a8e8afc5dfcb0d422bd811ba9b7770a663b081dbb" +
+			"40aefffbeabca955a9638830f0c5d70663cbf5b26067cd061c4a3f5cf8fa" +
+			"4b6678d82d9a2aa33f8538b7499a3466f6b0ae2a1daf280ab91a6c220684" +
+			"12705245f353b4b83db50bedd3bf99d42bde6363fd6212cb745467acb007" +
+			"b678128f6580629a06171f7f3af272f8900b801af3bf47439167871e7b0c" +
+			"33f198333992a6c52c32be46071738cfbf245937d48f816ebb88ff0e726a" +
+			"dc41de4c771ff0bd320a4c0b1fcccd9fd6c42ec9c5185943c70e9a4b7c26" +
+			"a980afe104bb1f99576671a254704c7d4233eaf9915e1d56c103ba9f6e8a" +
+			"46aff466933bf58c9842796ae9cd21f7ac6aa96ef42ca54e390203bac354" +
+			"b7c1de7d1887c48255201335f819020e2782a2ee8af92ceb206b651ae92b" +
+			"3f4fdefed05e08974aee0a353d104b1be9a5e75c7f958f1981271b0a6928" +
+			"05a7a2f28a0448d86102b4fadf9ab4ec2f98e31e64fcfdf2b524780b3342" +
+			"7a2a3100c2032fc93199f3ea7a9e8063fe73282dcb1fafaa9496c7da868f" +
+			"dcf33bbb761df0bfc6fef30fadd2b6efef4fd3216a8aee48a2ef28102491" +
+			"cf7278b567c272d1064a277eb193b3f6f01df641ddb729f72454943cbd3b" +
+			"671ec077f9e3548f5f57d063c653ebee4f228a78f8a128d26f7f4b44160a" +
+			"07e942bab87b2d043c77ecdf10c1a419e0a1c4162a99c21d4abae0558b8f" +
+			"4dc0b7f1ca3892a6babf71f2f70aaca26bb813ac884ee5d71abd273ff1c4" +
+			"add230a771b678afbb12a1ca7fbcb2c0f5589c9ce67fe8f78a8db87825b3" +
+			"09ca34f48ac35aa7ac69c2fb2423807650fcf47ee5529e9d79dd2628718e" +
+			"230ffe5b83f9d5bdfd9c5d211282e71cbcacf972995bf1b13d21419f7fa2" +
+			"8829ed1dcc459da35883b9269a474f7fceff01d44ab78caf1ef7d8117f50" +
+			"cc83eb624062b149a6ed06ddd1cd1feafccdee7122353e7b3eb82978ca69" +
+			"247fde52d2d6cfe7324f04af5259e1b5c2460889da4541b431ba342a1c25" +
+			"3a1b1b65fce7120829e5466e7ad2fe4e0f773c7c13954a9c92d906c91aa1" +
+			"de211f40916596bfa8245344e257e5907a2c49ebcc864cfbe28663e700d8" +
+			"472c50355313d5cf088e9e8a19cdd85bcfc483520498c6386050e53a3ff8" +
+			"1e2b77b55b116a853d71f60d621265166cd7e95ff5cb4466226d7cef68ff" +
+			"d0a35b61e76a43cdcfa8da7fff9558e2f89b981ec6be632b126303ca1fe8" +
+			"53d5c628d967d39317b60ac904d6a882beb0746f6925a86693aff4deaac2" +
+			"e5b64b611de86767d55a6e11221605508b1c5cc828251539b1b6f65c2c04" +
+			"8e65be5422c1b11194eb687d906c559068c0a810713b23b30d8b17f10df7" +
+			"0962c5e7e782aff7bb95adfe4cba9d90b0ebc975fa56822025100b5cb8b3" +
+			"8bdc8928c1a2a8034dd66e2a763696d7ce6cef4dd586b83f7d01749d37fc" +
+			"4fe8d7abd324d4ff1efdbdbfeb0a2fbb8b266fc2bce8e5e5b95d0089e7c5" +
+			"d7de4db837d1822ac8db8198889d6bfe778d0b19e842f12b5afd740aaecd" +
+			"e36e2cefc2cf0b082aa0c4f75684d024b8d828d8f2911fe1aae270251f62" +
+			"4f49584e40bb193577c9d8e04eb16c094653cdf9a15fe9210f724c7a7c73" +
+			"74cfd1a74abb5ceae88ea54f7e7569f8eb674529cbec965ed05bb62f1968" +
+			"8fdaa97297268bfeefd06eb21f700cc56f9bf7f6cecbbbe7278ada8399fb" +
+			"960371a2d5cdb852b11c9fa17650e614c5297bf46cb7889d52bcf49d2560" +
+			"720852822b75bb16524d88273cb366b84b88282da91875562e5a1fe73973" +
+			"afe90e5cdd3f5381612d3ba7bfa058d023a9326e403ec474d8938313fb32" +
+			"bdb5bf899b900c3818c43c8a0af6a061bd26e847ed75983402ee8a9cf4ef" +
+			"85bba5545a0d329ba81495157eda0286f1917de512fe448251697dea406d" +
+			"a510adcb05",
+	},
+	{
+		key: "b78d5b3019688e6ef5980c17d28d7f543ca5b8f9f360f805ee459717ca0d85a1",
+		tag: "f01babc4901e957d0c2032a7279321e1",
+		in: "ba7d35b2ef8af1118bce1e78018c9314b0c8c320591e103d23f715acb05e" +
+			"dc98fbc618de06627661df5842dbba9f604c2d20d664e5db06e949b11d49" +
+			"665088dbafdb0d39d20beaca7d723f8dcdc57e9c5583d303b6cdfdbecf95" +
+			"7d8daf2f1c72b2a6fa27e3d18841f4841abafd334c110cd2b74efb6191db" +
+			"ab9b8fc8427ee17664082f31db98d30bf15dda967e20730a9ef525abe9f3" +
+			"f620e559ed22bf74d347c9869f0311f33da7f1a3dc858b3a8aa73a35989d" +
+			"b055a4a2c269c95e352259c57de8b94d8de48984ecde426d3ef60ec1c7b4" +
+			"41cc950f7764f55bd0cf52d069b9ad446d1f765f35d02ec104ffcc00bf1e" +
+			"dc1b951ef953acd19984ff1b41041bea0e9f5326a7c9ed97e6aab42174ee" +
+			"971ea1dbe2fd1c1f67f977ab215962b0195417170f6b7748fd57262424d6" +
+			"cf7c235b34425f4047191232722932213b3eb73904cadd6a2e9c7571d7c6" +
+			"6c2f705b5039ff75e5e71c5aa738bf4177653e6eb0b49303a4bc0e641e91" +
+			"2691f217296a3325431d578d615afddf47784e4618a2ca40ccecb05d621d" +
+			"a52f272b8cf84f7fd8177c83af1580d25a764cc06436d67171cb5d1e3b39" +
+			"367b46d9a59d849d87ab6bfcf3fb9bac2b1ebfcd1cef4459e74b0e1b7080" +
+			"dabd2dea79f75581a55de63c4b23ff67d986ad060102933fc6cce8d614c9" +
+			"c86dc84068828dd9e21ffc5665c809d83b09432fd315dfce5d7a4ebd8143" +
+			"181953e3f8716e47b0b30cc1f753e31a7d509f2dbd4177b6da310cf3cd02" +
+			"5db270adf98e96259a5ae1b81f5be4d5c76f502a612ca73c76b91e0ca695" +
+			"aa921f9489948619482c2956205ae71fffc3aba4476ff754e4878e36c763" +
+			"2c935c076857c5b90cd63ea4764efbcee53e2ddc9bdce54b1cbbcf0e7544" +
+			"d023e7c2b79419ad92221a1f76abe31a8236e370d38e2493cc9ca2aaa811" +
+			"30fc713d11f500fd071d6eba6861e8b0859b372e62fe60b627a96c377f66" +
+			"236aedf307e1d148a61bdad072b93d7d2a73367c595b1e048f7023e72729" +
+			"1ec508326f5424a5bbf4e010d0240b71fa9137e6642ab40c5e4fff79877d" +
+			"b3253c663a221b49b3e77ea307c7b9f3f72a0f3a54d0112c45c64a0c0034" +
+			"baf2b55ae36ea6f811bbb480cee663136474dacac174c73b1e8be817916c" +
+			"fd4eb1876582bb3a36cfbabad91776aa676305ddf568a86e3a5eb687fa81" +
+			"67771fca7b5ca00e974b3cc3e322b4bd9bcee2a87d0ae7976da5e04fa18c" +
+			"219fa988d4f6fce62f194b05c26ed3ae1b066cd9751a2d916d53426a454d" +
+			"58f9c3b2fb49374e5791b412fdee1b6029144f1ca787f56fece4f64f4fac" +
+			"bfe4cfd8ba7c807a83cf44008fe5126a283ab2631a87acd8e2a3bd10979c" +
+			"4b07a84a49b0687a45a4798ded0b5e9b2acce30e714d78395bfa8f33ca91" +
+			"e68b2138bd67d8a694cd87c88dcefcd101a3b408d7a9095cc6a4b38898ec" +
+			"c8b375f5a67deaaf73eb7e99b10314ca6bba824658bee85dd731d9a1475f" +
+			"976b7c0aed4b67b088f0db5ca5091273217f724969dff6cf184181377c45" +
+			"5722beb23fd9d097a82ea2d8d527ba6284acc20cb30f2e52af28800c61fd" +
+			"1faf9f4f619550e0162a1a63758e202533889b27420fe7d0eac9a47a6e11" +
+			"1d80054412340e0426cdddbb3c7b9b823b8db3ef58230fad7a3ac21a7805" +
+			"d30878d4ea78dda95c951b7a5dc552e9434c35e03e1dd88652d3714f8fbe" +
+			"a39936cc0717c2e0335371f2a751204f5d9386baaec853f019325edfd1b0" +
+			"719d1fdac3fbd774a64bf957fc54039501f66df94b5b9b82c2076c597065" +
+			"dfcfe58b2e215a3734066aeb685ef97759c704b5f32dd672ba59b74806cf" +
+			"ad5daeeb98d16f7332ff0ca713d541c84e4aef0750bab7477ea707e2e497" +
+			"e12882dbc0765106070ec6a722d08fe5c84a677817b28fa3a41a6117f2f5" +
+			"465c2a2f0eb2b8be4f36e676b4115008bade3573c86cfb1370c03b6b0dc4" +
+			"bbbb0ada4dedac10a593655068a26febc2bf10d869cac84e046c9c846ce7" +
+			"927431f606f07b92abdfd81260199ae05ed01dfa07088c56a6a8de9c6d51" +
+			"d61d6a6d3f9904c216ea8329467a006a3d2495a768a39ef99a21827d2def" +
+			"909bb743fed7209f7fe59ff1c1e710095b05f166c6173deef5c6ec4105c5" +
+			"fc3b87c8269c786bebd999af4acbf12d20453b125f338aee87e9509ee405" +
+			"9c9e568e336304d7be9ffe81d1700555b0800242d9b7450d7256f2b17f6e" +
+			"d46a39f67bb2980572ce73169e352070dbafd4c7fa5a6be78cf9b72981c0" +
+			"a01f1e1e30ee3736c59828b791d2373799854497a28a44bbe0e074925723" +
+			"4986696fbb06ef9ea83fbd49c45a583ce12ff10258ba06127c67b0f66dd1" +
+			"09f1366d8036853973d8884f93de54fb2a12949eefc020717eff47898cef" +
+			"306b5de068411f1e113ffdfe2556e0faedc3e27d95a45b8afc15ba0eeeff" +
+			"eb86da7b4324e20af80c62bf0ceb4aee1515f5912f71c6bf2febf20123e3" +
+			"dd3a82dc1e58a108f1039942dcdacdeb1f0ad0b2ef34488d98d6a52311ae" +
+			"acbd03c12f6e775e375d5979c7c295bb049f2cfd3580e3da3841ddd8e6af" +
+			"4de5e6512ca79cebcab9280554524881da37984d340e8f0163fe10a02ed0" +
+			"88682560bc6d3c4dbcf1a542ffb3dcc2ed16a2eb96896e8269697ffeb50b" +
+			"73f2cc354092e782a0072fc12e1eaff117c2cc8a5a1ad8b47802ac9e23fb" +
+			"91a0cef9e4027595e0885464e61563093ee2b1dc5f22dfd04af7de6a70d5" +
+			"977d3751a4b3cc0c71a71c59c0534cb1f8c0eeddcf1c0e1b3e5ad0d083b6" +
+			"6e8b998ddf9ae9d3b365c851d42e995b9afdf8d66b2ac40bf514ce32e456" +
+			"0880afd38c42c08926067eb243c4b1184e667ba756c14ace5f525eb48df7" +
+			"ebb429d0a23d159664f8021d27dc7167081de331c7114c9c6456e1ffdb42" +
+			"2172a81c06d8deca995e158c48df27261a83f83e0127f5e056a139be9b76" +
+			"e25dadf534d3d1ed6ebc0b5d77d51e5b90ff86f30d4023066115bc11b33c" +
+			"c827b1103098826d0bf8777176b2da6f1e5b580e407ccf7e614fdf4f5b53" +
+			"3ef6d30b20c1bee61eab90e983b1a97173a62720ffd27abb8976a948d532" +
+			"d06596c23b0ef31c79831bead8f8e99ad209af3658cac0cb3c3f9c88379b" +
+			"9bc871d8e84171d53400902da1243f664afeaff60bd96ba2639a7644676c" +
+			"a79f43130af12ba2c877d67f7ec030a4217a72f5368af7c9f24e643db6ac" +
+			"97a04adaf57dbc53762d8dfa1afd49667c4041adcb5ec303e191b786273b" +
+			"bb065cd9f16a3a4a399c6a7aab9c1a6604998264e8b3dbd13d8f2228b13b" +
+			"2c2b9fec5055d8e9f2df1d9a25e4bfe2029776389877bbef7e2c7621f06b" +
+			"c0b7fc0786e2b2d042483ccd4a59d2872a6c5ac73e217123e5c8401580a8" +
+			"d967e0895aaa28f4d25ce68c90b4394d8113bc423e9fae46ac47bc2ac191" +
+			"fb97b80b5a85feb2bb54f84c493235c1408662fe253c6786fcf6fdb8be87" +
+			"dc66a72cc847f94dfb5214af5905b7039a7363a1b23a07853daa26862783" +
+			"ba08a80846fbb93ce98700a4f9961115128dd67bd7d19e0c588fdf6196c1" +
+			"1cb0154002ae862f11421f5dc3a57b6c0870b452272be556a1d14eab1af0" +
+			"a91ff5b89de6bbeed6e03bc64f5efddf9e54da71c594bc5ef78e0192cfde" +
+			"da36e4ad1a6b0b51110c1b24d20dea1f19e18cb1184d80189f842d4f07ac" +
+			"834744dd009aa3771b1e5502fe4b65a403a4bb319e1880ff6ba852e90a8f" +
+			"4fcb52cf374c88408428cdb1255291b04ed58c992310955198d61fa1fd9d" +
+			"762d48f2f65a287773efc67d549981c291b427889d3e3dfc0cc6cd68415c" +
+			"dbed81b516786dacf431472a7dfc99688d15bb6c1b85b1a2015a106e5de8" +
+			"cb9eec4c80b17d00fdcf4a9c64de4643a95dade8fa9f1bc5c839037d86c1" +
+			"3800a244188e3b18561a74912ed72f99f2365f0126732d037dd54a3ab77f" +
+			"9a9f6a1c1469ea92eb707482066bd4990dec4d7614ccb4ea6dd4deb8bee2" +
+			"2c4dc0b9b4d4cc70a500d2c8a5ac3ef88a38439b7dc254a6d920cfd317a8" +
+			"4d7747148c65b6730709e43369d4c995b03c58b9df444f77f216944e70f6" +
+			"6446554d8d513b8f7f28ef0a2d7ad5ca2f6110304196953247a7ac184f68" +
+			"61fba896c2d5a59007ec2b2c8e263957e54cdc1f3b4a145228823fdf0960" +
+			"c33a28f59b03ee4be21001d2f56fd49ed14db33b2c4eec2c3f41b250a624" +
+			"99a9b6602c1e838526a54cdcd058af1c252d56009d4c7769deace53bdb66" +
+			"543f5a081cdde775e61efa70956fe2a7a6019a164c6e413ded314bc928b4" +
+			"aebccb946ffdf3eb33e187bf421febe26112b3262a526de65678cd1fa03b" +
+			"83513705108fe0bb87aa99aceb28af3641c46a2c4427cc1063de01aedaea" +
+			"fba68155d4de494a27ff6b7fcc8f5c5c3f7d3a115c397a1a295bc55aec8f" +
+			"7f150cbce2a8aa4706d54ec863877bb966ad441c57e612a1b5d438b98d9e" +
+			"fcdfe6d4f66e885f96407e038015cf974ae5a3540692b054d2ddfde59b28" +
+			"ede7e2f581eeb56c5b88e2779aea60c1d8ca6107b0cdda1ac93e6c7520da" +
+			"edc66afeed12f980e20e1e1c327d15ade4bb90de30b011a9cb33855ca3ca" +
+			"e2",
+	},
+	{
+		key: "2b0b0fd3347e73c2fa3a9234e2787e690a11aec97a1c6d555ff7b4047b36f372",
+		tag: "81b1a6633f849ab0aa7baafa58a5d9b8",
+		in: "427f3a7a5f1142ffa68e83df5f917e07b2bc454f3adce068a8ae9e0908e1" +
+			"3e0099aaa9074697593c6d8c2528fedddeca05e3888be1a0a201c389a72d" +
+			"20cb661017544d95a431e70e7c6580d8fb46ea4495bc59db6ae2cd69510a" +
+			"02426c50de1b6110120f759960605aca718d4d0a497e003e1ea2b8ae9a53" +
+			"df3c1eb4f704eb32f8f05eb08cecba0fd4a94f0daa3b0984c30a38f94b7a" +
+			"10cde723182d30588bc40f1f9d38a3bab4800fdd5148e34e396144763696" +
+			"c9b3e9b8adfdb337123d54237c7413f98bb2056152b256e37a27bb947c67" +
+			"240fa3ce8da62ab367db540bcdd9eb873d6c71c75a08fe99b5c11ec8e6af" +
+			"f926d2adfcf073479de394d4aac5fdc6241824d944b8773db604c59afc01" +
+			"495ee755905e5616f256c8a64321d743a1c9368d46418826d99b762e2f6b" +
+			"f998d37a995969cdc1de85f0ce3987c6550459f5e5bfd9173bfcb9e0112a" +
+			"d91f092de446beba14fb3b8ce3fb2f9c941815b2cb5a3b406e2d887b7912" +
+			"bba07c8dc7caab9836827da93ca71fa5ada810da1e5e9b09738524564d8c" +
+			"923746d19c78dc9107b9f20f653e05d7f2eb6bd90cf5eb30fdd7b587eb46" +
+			"74a1064c70ef0af2e75373044d32b78d96eb1db3112342d38dca0e47b96e" +
+			"9307fcdd711b1c66355186369a28481cb47ef6bf6651c2ff7ee4665247cb" +
+			"12b573933d3b626d1c6264c88bd77873c2e73e73ee649216bf0b6d6615ab" +
+			"245c43569d0b8096596f25ceca8667661de1cd60dd575697370ebd63f7e9" +
+			"5333e8a2cdb829b75ea83d72cd246d50358f7c094c8a515805fda03165d5" +
+			"21391617c9f9a2ea562b419632df611a67912d2b369e5e505dbd5c719253" +
+			"16d66cd608cc4a9583a8eaa4661b7279870345fac3031631c1a220551527" +
+			"5be7d8d89b71960e687aace3a0e8f206e475053d6fbf97717b154c75406f" +
+			"2caa97d1ab66048f1c99281c188a2f37b8bfc736c25840a9130ef2031c05" +
+			"6acd9dc10592eddf94f5bac85319b10ae46cc136a0738aa803837287ed7e" +
+			"dafe08d1fcf31d5e63763e39a5e1f4d7d0edab368d44e63fdb33c28905ff" +
+			"d6be406a024c017081b4f2d70860776e9d2556cd008fa5017b58733da13c" +
+			"634938407a118827a80baa28d4e605db59430f65862b90cd8356baa287b8" +
+			"4e6d9199fd80abb9fa697e2c2c4c760128e4ec0438388cf407e2a2fe0f57" +
+			"908187ed8efd4c5cb83cc91dbe6a11444eede85099149ca82921bc28bdd6" +
+			"b9999594a41d97307f8854b1bf77b697e8cdd4daead2aa49fbc571aa44c0" +
+			"bc84a57cb5fd85f06847ad897ceaf449eec45bddd4e4eb1e1e119d15d5e7" +
+			"90957e686acbdda1bbe47ea935ebc4b8c2e3cf9b7157cc6dc03bcb19508d" +
+			"a9e19cb76d166da55559ec7e0995d9b50c6c45932d5b46eee400c56d9dee" +
+			"618977dcf6f76e3e86bc5207493afbc2aae9f569ec9277f33d9f61c03d59" +
+			"dd6d8250ee8cb3e54e5e941afb74f0735c41d52ef967610c9f55b2b52868" +
+			"4b549a99ae3392a7237bb52ff5f8d97327e2837268e767bed0bea51f76bf" +
+			"88bf0286bf22b881f93f1d54fab5cd4e3c148c96c39e7aeef375de249df0" +
+			"4d89d1bd97a7afb2be0cbfd3380cb861d31e4ad1ea8627721e4518b9db3c" +
+			"cda20273ec23549c4adc3c027e3ac9558de2010a0263c1225a77dac8be60" +
+			"d498b913f91391d8b2656ffddb06e748cb454dc2b7226745f11030a6b9ae" +
+			"09ac8ac428d9c6500801fb540650c94610ab70465b1210c6db2064dc84dd" +
+			"7f52573f8f40c281470e85176c85ec6de3c718663d30ad6b3dfc1a3a9606" +
+			"1936744357ca62fb8bb066aa1fcac6d7a2adf0a635cd546bef39fbd3ee0a" +
+			"8802ab0466ec9b049b5892a9befa4377cd199a887c34569b6f90852139a7" +
+			"86babc0049ee2b527aa96b988237a52eae8b4b49d2ee15ee5294118cee62" +
+			"3c3e11cecb836b21af88555f10be2eff8379beb615b7b3d6c01d545cacf6" +
+			"61be8ebbf7a3c58ac5e0e7b17997659a2bf15f2b2e3d680d142fd29d23a7" +
+			"aea9890f3ff7c337fce49ecedaf38573edfae07810ba9806723e576d687e" +
+			"a11700b8ccb96a6559259c367cef4e3999a05a373ab00a5672ce8b3d1dec" +
+			"a414187f383e449d10021b73c1f7e39ce01516b7af96193f9993036049fc" +
+			"72ac059ef36b2bcfbe13acf140d41592880fb8294ebffb98eb428ce9e65e" +
+			"1094521bcf8ecd71b84c7064539a7a1aac1ad2a8a22558fb3febe8a44b87" +
+			"72fc00c735773d4ce2868a0b478ee574b4f2e2ceb189221d36780b66212c" +
+			"dd8fd3627cf2faaa23a3d0b3cd7779b4d2b7f5b01eb8f1d78f5b6549c32a" +
+			"cc27945b5209f2dc82979324aebb5a80ab8a3b02129d358a7a98003e701c" +
+			"788a64de89726da470010eda8fdcf3da58b020fadc8970fafb08a29bef20" +
+			"2bd0707e994015258b08958fc2af4c86c3a570443fe6e1d786d7617b0c66" +
+			"29a6d9a97740c487622b5b8186c529d7f8af04d9f0a9f883043f08103ca4" +
+			"d70057ee76639f3b1046d86928d54cd79fb5bb7b46defdf15d2f8578568f" +
+			"1d7b73e475e798ec6812586700e038ed4791b23ac9439d679a1a4bc04cea" +
+			"e328330c24b065c9cdcdcedfbaf58e5299779e6f48783d29ec3b1643bc8f" +
+			"1095c724dea75770583b15797fc666f787510d91e65a8e2090cc1ed2013f" +
+			"e63ab17bc7640ee817487f4eac8326e9c4698cb4df05d01bae8c0d00fc00" +
+			"08919484d5e386c8f60b8ac097c93c025d74faa56e8cb688d1f0c554fc95" +
+			"aae30873e09aae39b2b53b1fd330b8546e82d9e09bbb80132d794c46263f" +
+			"4fd7b45fda61f86576dec52c49f2373e4dca31f276d033e155bbcdda82af" +
+			"8f823948498f4949bf23a08f4c8ca5fcc8598b89c7691a13e5aba3299ee0" +
+			"0b479b031463a11b97a9d0ed3189d60a6b6c2390fa5c27ce27e28384e4fb" +
+			"04291b476f01689292ace4db14abcb22a1a37556675c3497ac08098dfd94" +
+			"d682401cabec239377dff592c91aca7eb86634e9d5a2848161dc9f8c0c3a" +
+			"f7b6a728371fac9be057107b32634478476a34cbc8b95f83e5b7c08d28f6" +
+			"fb793e557513ca4c5342b124ad7808c7de9ecd2ac22d35d6d3c9ce2f8418" +
+			"7f16103879ed1f4827d1537f7a92b5bbd7cd12d1ecc13b91b2257ad073b7" +
+			"a9b1ea8f56b781bea1bddf19b3d7b5973f1065fb72105bb4aeecca5b7513" +
+			"ffd44d62bf41751e58490f171eb9e9eb6d57ffebedd4f77dd32f4016b769" +
+			"fed08dd96929e8efb39774d3c694b0d30c58610541dcfab3c1cd34970195" +
+			"7bf50204acd498da7e83947815e40f42338204392563a7b9039c8583a4dc" +
+			"faba5eaf2d0c27ada3b357b4fccd1595b9de09c607ebf20c537eb5b214b8" +
+			"e358cd97992fa5487bc1572c8459c583116a71e87c45c0ba2ca801931a47" +
+			"a18ef0785ebbe420790a30278d2d0d42a0225d211900618438d1a0b2d5be" +
+			"d14f8b4be850dc8cb08d775a011683a69ee1970bb114d8d5017de492f672" +
+			"09062d9ba3616e256d24078536f30489e4dacd6429ed37aab9b73c53fdd8" +
+			"a8a7aff1b914b9d82d75a46d0ccf85f48d3ce9a8d3f959b596ae9994ac3e" +
+			"3b4af137d0c8e07ece1b21fd8aa05522ba98f85a7ab24ed8c1e265fadf4e" +
+			"9a18c5ab5684d8ba8d3382ad53b415c73ebfaba35abeebaf973b6f18e0d8" +
+			"7f019420eb34e09bbb12afc5b149f1e9e9b6ae36ebde429d437ada1a2d52" +
+			"b998f7c75ef731132aafc3bb106a2ad3ae11223a355804d4869ebaa47166" +
+			"2df261d95d48ac6eb17c1781e81c0027ccf8f05c39e1eda7793cb16622be" +
+			"ce7a1ad5d2f72f8bf4bdb2f4f4dcadac3db3bf727f0d447adddad4500360" +
+			"09ee011bf4155e5e46c74b00d72e8e6a88de9a81a5a4685651b90e874dfe" +
+			"eba41698c98370fd9e99619ce59ebb8342417d03fc724f9c910ae36ac5e5" +
+			"b46c424141073199aaac34232a8e17ebbfdd80eb75e82290de92968f3893" +
+			"0ab53dc83ac433833576e86fbabfb9d7cd792c7e062811f4cb017710f841" +
+			"1e0fb65ea4b3cd68b0af132cb08330aa13579196ec632091476f268b44ba" +
+			"8f2e64b482427dfc535d40d3f58b4dee99053b35a3fed1cb245c711fa16f" +
+			"c141974c8db04f4c525205dad6ca23ccaebde585cd3bc91f5874452ed473" +
+			"08de95cb6164102744f90b3007e511e091653c97d364fe0cbd7f4cd3249c" +
+			"1f5c452becd722ccc8c6b4e371e2631337dff78efd903a8fc195a90ca5a2" +
+			"aa4513bc63cd43794ff06c5337329055c43d4fb547e63d6e4d14fbe37b52" +
+			"1411caf2f1b0df51a68f677db59aa227c725cf494ccb7f8cacc5a06ac5bd" +
+			"f135a2603175a5fd5e5af615fd2e7cea61934e6d938b9e672290aaccd99a" +
+			"7e26dc55efe928e56ae6354168264e61668a61f842a581cd0c4b39e0e429" +
+			"04631c01320857b4d7e260a39c7fbed0593875b495a76aa782b51fee4f88" +
+			"84ca8ddb8dda560b695323cdde78f82dd85757cadea12ef7cf205138c7ba" +
+			"db6a7361a8d7868c7aefa7aaf15f212f5f5ab090fd40113e5e3ad1ab04f9" +
+			"b7f68a12ad0c6db642d4efb3d9f54070cc80d05842272991bcdae54cd484" +
+			"9a017d2879fd2f6d6ebce27469dda28ad5c345c7f3c9738038667cc9a5bf" +
+			"97f8f3bc",
+	},
+	{
+		key: "aa3a83a6843cec16ab9a02db3725654cb177e55ec9c0c4abd03ada0fbafca99a",
+		tag: "719dbe5a028d634398ce98e6702a164b",
+		in: "643883153c215352a4ff2bb2d6c857bafa6444f910653cacd2bbdb50ffdb" +
+			"cae23cc297a66e3afefbd85ab885e8ccf8d8f4930e403662fb4db5121aca" +
+			"82dfcc3069bd5f90be4f5bfd3c10f8038272021f155e5de0a381d1716abe" +
+			"0b64b6d0f73c30baf6ddfe0e6a700483cad0fa14f637afb2f72361e84915" +
+			"78ba117e1c03f01fd61aa8f31da6464f3d0c529524d12dc53b68f4d4b326" +
+			"db7fc45c63f75244002b8f9a185556f8aab85948647818f1486d32c73614" +
+			"b8c4763e2645bdb457721ff3901327588da01622a37ccbbd0374fec6fd1b" +
+			"cce62157e64c4cde22c3a5f14c54cd6db63db0bd77e14579989f1dd46461" +
+			"4c8691ef26406984b3f794bb7b612e8b160374be11586ec91e3dbb3d2ccc" +
+			"dbfd9c4b52f0069df27f04853e7cc8b2e382323345b82ce19473c30296cc" +
+			"453f479af9a09ec759597337221e37e395b5ef958d91767eeb2df37069a4" +
+			"f3a530399961b6bf01a88ce9dfcc21c573e899b7951723d76d3993666b7e" +
+			"24dc2570afe738cbe215272ccedb9d752e1a2da00d76adb4bc0bd05b52c3" +
+			"fa08445671c7c99981a1b535582e9b3228ce61662a1d90a9c79afbdcfcd4" +
+			"74def2b7880cac6533ba0a73fa0ba595e81fd9a72ec26965acc0f4159ba5" +
+			"08cd42553c23540bc582e6e9ac996a95a63309f3fa012eac14128818a377" +
+			"4d39936338827bbaafad7316e500a89ed0df7af81be99e2f6aae6bb62568" +
+			"1dfa7e100ebca5c8d70f67be3c1e534f25446738d990ee821c195c98d19c" +
+			"fd901e7722b4e388da90b95ac0b5b5dc5d052ad6b54f6ea34a824bcf0cd8" +
+			"7f1fc9a07e8f5b8aa0793e3c9c1022109a7c7ae97ee2a2867fd0cf0f8971" +
+			"34b3d150d3b24fcf8323de929b73cca01244df02510393f0b3905caa0268" +
+			"7fe35f64391e7d4b30be1cc98319716528ca4f35bb75d7e55cf7749968c5" +
+			"37136eddb149a9f91c456fde51937c0f35e7e524647311077e6fbe7f3c12" +
+			"37b9584fcf3b0f78744c7b2d3b452823aca06d144e4463eb5b01014201cc" +
+			"bfed1adf3414427072135d48e705b1b36ab602cae69428e7c19d39cbb4e0" +
+			"ca26a871d607ed4daa158b5c58a0a9f4aa935c18a66bdeff42f3dc44166b" +
+			"a299d71a2141877f23213b11c52d068b5afadc1fad76387cf1e76571e334" +
+			"0b066ade8da02fe3b0bdc575b1d9ec5d5f5a5f78599f14b62db0bef7ccc6" +
+			"1711482dfa4787957d42a58fdc2f99525c32962b06492229399980601bd2" +
+			"ee252306b1464914424de9aa414a0a6e5dadf8ffbf789e6d18a761035d3e" +
+			"f2ff0753becbd2dd19fc1c28f9acebec86f934f20b608a9ef735ac91f6b7" +
+			"83d9327cce7f4870d39bbbfb0100838dee83e6baf2b40cfc98415dd174ed" +
+			"72e393ad0459e8035dce7eb18eb3af2f39d2712846b9e1852cd61d06dfc3" +
+			"5e34fb761b67e2a711ceb4a82557371ed32ca8db2e4cd7fea0b6bd026177" +
+			"4057b9abc45dae6869cab1097459473a389a80a4523e5de696554f8b0bec" +
+			"0ca605e6acfaa00386fb5a48e0f5893860a29f35e680be979cf3bf81ee7e" +
+			"ed88262dc80af042b8cfe6359cf8b475560bb704728034e2bd67e590bd76" +
+			"1632e516e3292b564c7265d7a6dc15c75ba6f6a447b1c98c25315ac7de59" +
+			"9edc4993e4dc7d1dbfcea7e50ebd0b226e096500216c42de3abe352e5b09" +
+			"a3c9754aa35d00883906599c90a80284d172a90abbeaf7e156fe2166ada1" +
+			"794420fe55b1a166d752d0eb7f04e822d021c615e84777101e7c9f9dd12e" +
+			"565b7d093fe978f85e6142c1ca26798b45f4b8d23ecff6be836e810e314f" +
+			"ebd2ea66f2ac95bad84b39b7a6bac41448f237b45e9ec579235ba2bf5fa1" +
+			"f00286379ec107c743f06ae0d11b57a2f5b32e3bc5f1697aae812d7ca303" +
+			"b196a8a43259257f7697bae67adc7f121be561b2d0725982532ffc06cb22" +
+			"839d9066dce0e4d683d9348899089f6732de62751ca77f1c439e43054468" +
+			"2c531b9c61977bc221b66030f7571dfb3ddfb91d9838529dbc99612f650a" +
+			"d72bb78de061192068941a81d6ac341101aeb745b61bd7a87a35a2714d50" +
+			"c3eb2c3ea148fb9ebed948307f8b491aec277ac01903ba36e6ad54f89fe4" +
+			"280a17f8e7ae639e75aec16d56576f03c2a1efe4af995eb825ccaa6efe0f" +
+			"d6d878299a351591d791c286cac5cb049834580d47a9bb7720d0603e3141" +
+			"ad7c1ec2dd23d3002e15d73c1828a7f08062848b1b6fcf816bd954743547" +
+			"6f0d6f882125bd03095eb1b1a846d535730e258fc279f7095de7c2d3fcca" +
+			"a4640a2e2d5ce0974c1e073c60bb78171c1c88ae62c7213a95d36ea9ab17" +
+			"59093813b85d17ff106e69100bd739ede9656388bf47cc52730766a8a186" +
+			"9dcc623e09e43cfba1f83ae1d9f16789064ec73504c29686760ea02c6634" +
+			"a929ca10c6d334b1751494c6d143671ce8e1e7dcc9bcda25af895a193032" +
+			"ce27c1016ccc4d85507fd2265ebf280d3419f54f66ba2a161c068491578f" +
+			"be056f02f97be745db443e25ed2647c5348f278f4ad8bf5b2a2c2d56e795" +
+			"532e25585984a3a94f435ef2742a0413abed7230ff2e9724187c91f73a7a" +
+			"726ebf36bc8d0d959418dd586452664990889358c56720c1001c004ff768" +
+			"54b9850890ce1b31735fd9f4a3640622ef0b25c659e8a937daa0df7a21f1" +
+			"77be13dfdb8f729da1f48e39a05f592d8c98da416b022fd8edab8e6132eb" +
+			"a80c00501f5cc1e0243b6b096c8dbe7f8c6ffa2f8bcc7f309fb80b489b92" +
+			"c4878fabad42d91876e10ee64ccd415124461cdc7d86c7bb6bcd9133f3c0" +
+			"dfa8f629ddb43ab914c0ac5ecddf4398052229876fd838b9ae72523946cb" +
+			"bba0906a6b3ef26672c78cb24cbf691a5ec869d9fc912009d840772b7da0" +
+			"c7f47856037c7608705cd533918c207a744f75fdfac618a6981778e09332" +
+			"5c7d22170da85bdc61044b4c397919d601a30746cefefa798c58f02cb827" +
+			"0d130c813cbeb67b77fe67da37a1b04bf3f1e9ee95b104939220fb8a0394" +
+			"86ab8954b2a1468016f546406d1946d531966eadce8af3e02a1f59043ff6" +
+			"e1efc237dbf4dfd482c876531d131c9b120af8b8fd9662cef1a47a32da40" +
+			"da96c57dc4efad707a4e86d0b84262d850b451bda48e630c482ef7ede5bd" +
+			"c55147f69e2ff8d49262d9fe66368d1e38ecdb5c1d4e4042effff0670e69" +
+			"04e47d7d3047a971d65372126ff5d0426d82b12b253bb4b55005e7a22de5" +
+			"6fa54f1dfcce30b1e4b4f12b1e3c0de27cea30ce79b08c8c1aceb1ffa285" +
+			"c317d203a9f2e01d542874fc8035b7670f3648eec79561d6ff2fc20d114f" +
+			"ba4fbed462f1cd975ee78763c41663849b44cb2827ee875e500b445193e1" +
+			"4556bcccfaba833bb4ea331d24a6a3bd8ec09906c7b75598b44ce1820a49" +
+			"fca4a0c1501e6c67515d4fa7f88f6aa3cd7fbc6802131a7b14b219e154db" +
+			"9ed241133e10ace40e4d963f904dd9f3bdaaade99f19de1ddfe8af2b3cc4" +
+			"0a48374dd8eb559782bea5410f8f9a1cd128523c0157b6baad9ea331c273" +
+			"311492fa65c032d0d3b513d23b13b86201840d51759021e4133f873f2781" +
+			"8f54f34ba73b4f33107d49c8de1533856ec37bb440f3c67d42148765610c" +
+			"3296bce932c839fd866bec3762a38406ac2b39d0d93730d0c88cb8f765dc" +
+			"d8ee71263fc96068b538da06fc49e25dbeaa10a5111a9af8e8f8d78e6ed1" +
+			"3752ad021d9f2c6b5ff18a859fee9651d23a7237bd5a5c29029db3882c47" +
+			"0470de59fd19fb3bfbd25d116f2f13ef5c534bf3a84284ae03e3cf9cf01d" +
+			"9e984af9a2e63de54e030857b1a071267cc33d22843b28b64b66e4e02803" +
+			"c6ab5635291aefa69cfeb3958c09d0b37176842b902da26caae3f0d305e7" +
+			"c6ab550414e862e1d13d9bb9dc6122cb90ddb1a7bc6d31c55f146659baa9" +
+			"6cca4ea283e5e1639967889543ecb6849e355b6c0227572097221dd46c1d" +
+			"f8600b230e9644ba611ba45cd83fa4ac7df647b3be57387b6db12682018a" +
+			"de9be50a8ea7d5f7c743bf0c6382964bb385b3c207c0cdd63279c16130b3" +
+			"73ba974125291673344b35c8ef9a33be5a8a394e28dc1448f54d46af675a" +
+			"edc88ce85a11ad7e50058df4f3f2364abd243683d58a2b13fcb0dc0eed21" +
+			"380b666eb87f4be75e7f2842bae916c15af3e9658c55408537b2301faa6e" +
+			"42af4d94e3eda6a41d6d302be281e2a9299e9d0fb1f20cf4ca978e66bdd7" +
+			"4c8bea0f15c84d6513cdea787dacbd4bb529ed03528284cb12f6ecd841d3" +
+			"c58c3a57c6bc19b65d6d10692f4e1ad63b091137c8acacc6bc1496953f81" +
+			"2972bf6362cf883bb75a2d10614029596bf9f35e92addbb50315b30161b7" +
+			"de8867a1393d9583887a292cadceb54078c9c846ec30882e6ff987494060" +
+			"721d3c761940b91a126e8d1e0118617bdae01a7f9c1aa96bdd6c78ca06f2" +
+			"6c8d85664a8705334f4997c724ef98fe265985593d5a9c30798714e6de1e" +
+			"bd04b648be47a6b5d986a3103e738a5cd114b19b7ba99d2e2eec6181bf3d" +
+			"ff0fec8c54ae6118be8702c3e775d493a6fafb509712a43ee66c3f4b75b0" +
+			"194c88937cffa5fa17b284d2556f2b0eebf876e05f92c065515198bd5e83" +
+			"00d0db432cb256a4a0f9963a05694ffce3ecbd182209e0b7bb50120f6be4" +
+			"eeb9d268b17790ee14a2c887dc5753e0086630b3123734053aa37595aa8f" +
+			"31968ddae4991af4ab970c1e3cfa1146a2efd9dc42abd6af14777b8a0455" +
+			"3865691cbac4b4417b3fa13c154d581b498f3b8cb77adf0e42dc2f2fb521" +
+			"732447de97271e542c6cf8cad3ba0148cc3ba1f2983ead836a25a2c022d0" +
+			"43ba18fcd009d518d07b53344a5bc4d626b3b38405a114471f75dc70e015" +
+			"d11e8f6f57d087fa72909785573008b1",
+	},
+	{
+		key: "1793bfda9c8666f0839b4b983776735a927bdaa3da99b13c9f3d1cc57d4d6b03",
+		tag: "bc89cfec34ab2f4f2d5308b8c1a5e70a",
+		in: "a09f661aa125471417d88912f0a4a14115df9a3a19c1de184878291acb0e" +
+			"89ee1f9d8213f62df442f8969a9a5a7c402fea09bdbe236fb832544e1f93" +
+			"9cdd4873802b2bb8fc35ba06b7ff96da6dc7efddfeeda84116bc525a7fc5" +
+			"2d84d2e63cbac00b122dc64f2d15b36595259d81a1d2a09f204c54072751" +
+			"dd812259df1104bb2d2ee58baee917c5d0aa2649c8a1503114501e6ed6fe" +
+			"239847d3d88dccd63d5f842426b600079c6bf06e80a2813b2208181163b8" +
+			"61dca07fa4d88254e84dac1c78c38397a016b5ad55a6b58878f99036db56" +
+			"89871ab3c321f6ed5895f218f8fd976c348b3f1269fcdf4d38c9492b4721" +
+			"6c45f499f5705830b33114d721f9731acf6c69fca681b74c2d82c92e145b" +
+			"7bab77110821d3a12cc818d7595a5c60c4b5e5219376c38a4dd52d435d41" +
+			"562802ff65ba2bba5c331c333d5adf194d29b2cd9ebb55927bb4ec17681a" +
+			"3f5574ad34fb4e964f2c756f6dbbb7a6876a21579a515263444de7a30a33" +
+			"15005458bc137ccfdff18a3892fc9f58f1de10d4de20bbcf860f5f036d8e" +
+			"8a188f18e5cf7ea3cd260710e7491befcb131d49a28dfb1ef688fd021a1e" +
+			"e4420d32fbfb03b47f5e85c37d91e49a1b0db85d966eb5434c4197433eb4" +
+			"9d56f2ff999c9a72230447032dc949202468261b48b6ac212e3f651d6c63" +
+			"03a06c90bb2d3a755ed91ba73bcdc28e1c5b0936e51e0a9f69c3ebabd3db" +
+			"add7abab6d8f6a44daeb3126429a01815f57444fb7022a4a510f8b564ae2" +
+			"dd9779b3a273fef15859a33e233724846c30d89fb78a595b6ff6c834812c" +
+			"00a991e405806aafd0c26a788895ad00a5e43c5426197aa8247207077548" +
+			"ee67db4cd6f878431a2e36e952d84b5fb89d681f553198e2c066310ea6ac" +
+			"3a31f5b1792620616f6c41d486fb844eeacc7fd36971abf416e8d6d50985" +
+			"c83cc92ea46ac37da8f0026aba30c945d8bb15080d2d95e4081bad626199" +
+			"3f95f57ed3252822a7caa035ae22a36c35e280cbbc82d729346cacdb1794" +
+			"ae9a9bb2793fd1d5c47121b135c2836063367339c5151b4e35278e97f62a" +
+			"fdd2f231d4b47812d083a829ebb9c374ff2ae8479cc4b76d55f9cef3ec6c" +
+			"4894f53e8caaeb0d8cd072960cedaf758e48e3640590d4f728626e0a08ee" +
+			"ebf719c96bf8ed4d0c283be09c0ae67b609e22d3b9aa6b03642854909de0" +
+			"5ed52b39673867bf586a632ab8072de15c637cc212cba8387515c9c9c433" +
+			"abd7ba6b02abd09da06a34694ad34f88515b65c0c9c247fdf9819fb05a1a" +
+			"ea4728c1182f8a08a64b7581cd0fb2131265edcb3d4874b009aede0e87ed" +
+			"463a2e4392aefd55e008eb7ba931788262f56e53193122a3555d4c08133b" +
+			"66020154b15643fa7f4f5e9f17621d350ede3dc70be02c59e40fea74dbbd" +
+			"7919d1a8d4e22ef07c916fa65e7d4b89fb11a7c24ddc4ca5f43344c753b6" +
+			"1331c3fa4558738ba7832b5b2a275bc9b7989b6e6888865793329806cd3b" +
+			"f0ba57c941d4428623e062f4ac05e7cd79ad5446f8838f2b247b66bddadf" +
+			"540845a1bb304a04b7edbbff579c8d37e2f6718f8690abd5231822c7e565" +
+			"69365ce532449a41ae963ec23a2a75e88307dc6b59cbb3fab913e43ed74d" +
+			"841ca9f6e4ef96dfd9f04e29e89361aece439c0b2e1943b30410a63d495c" +
+			"522ac3ec1b04ec4cb345f7f86969957ad750e5bd7dbf1d6a22eed02f70b8" +
+			"1cb5b2b020c0694d7f63044f9de0c3de1ede52009c858992d01ebb92ff19" +
+			"a9e0fbea18942fbafb77746c8e9e687dd58ccc569e767528bde43b62c7c1" +
+			"270a5721f1212de2b29a7aae2d6ba6cd173d7fbc78aec4356ce2e8ba9164" +
+			"d97dec061dd0c3a0e3c520a7611ac99739049dd5825537c70b7ef660046c" +
+			"1785546cd99aa400da848eb7c3c91247415c8e245d0f14c30d482c5849ae" +
+			"aaeab2568288229b08267818dae8f76fc674c684c99eb5faf88a0783813d" +
+			"f7298e0b50cb233f78471e5ca9cc3b04927c26a3871cf253798cc49aa717" +
+			"d8f18a1ddcbdc26497d188f15f86ec494dcf8f942c3e07e572385c6fa0ef" +
+			"40c0b625f1737543074a747a369482a0b342a08b3eccac9f9209be31aefe" +
+			"5a7794974f71ac0bc9a58026397ea3dd4f5e40511d58d2a3b45925c194ef" +
+			"13987037d736dd48b509d003a86471d5f161e0e5dd168b4f1ce32f703b89" +
+			"15004d8dfc708a5bb02b2e6fb67424b2cbcb31ddaa0114c4016b0917382d" +
+			"aad11815ff5b6e37d5af48daa5ef67cee3439283712bc51b5adf2356cb2a" +
+			"5181b8941fd78945c7c9d61497683e44fee456ad345e12b4258f15945d45" +
+			"b6ca4369ee792d849112d583fdb39cd4d333ee057355f0abc8d1eea4640c" +
+			"128cc1617982db0394233dbd416102eec1874081247d2982bbf9fed1b1b3" +
+			"8f4da923d68c8975c698f189a4d7840fd7aca9dceb7d91c076f85e1c546f" +
+			"4d5de4f60c91348455aaea30cac134c844dad93d583c139dd52b3be6346c" +
+			"4d2e6864125c5a2d0aed8f67930e1ebf8700ca88aacc914ea76ff17148f0" +
+			"777738cc126e75a2c81110faf02fefc47c91edbab7814599000ce55fe20e" +
+			"f313566e9b62457acf2f22e1141e220bd9d4747417d03e703d4e39282803" +
+			"386327fc65dd597f723ee28185c78d9195fc70a75706c36287ab9c6e00e8" +
+			"5cecbbd6043c6af8d30df6cdd8777be0686853b7c8a55a5b1e03e4431d39" +
+			"1725ff99875a85cae6926998723b36d13ad458220712209bfc5e8d2ca5d4" +
+			"4ea044d5ba846b4035e7ac7e9885f55d3f85c0c1b3d09fe929a74450f5d2" +
+			"9c9672e42d3f59be4ca9d864a4322cc454c2578493bd498a51bbe960e657" +
+			"3e5dd02c4a3a386d4f29e4578a39e9184024cd28d0e86ecac893b8e271bf" +
+			"ce3f944d130817378c74d471bd20a4086f2429ed66c5c99969fd8da358ff" +
+			"5c3be72bf356ae49a385aa0a631b588ddb63628fd162673e915cfc4de56e" +
+			"ae6ff7101df3b33125c9bab95928f6e61c60039b6cc07a66f9c733251447" +
+			"ef9c1ffefa2158a8ddf89dc08686a4cf9b86ea09914e79842d72a3236afc" +
+			"98a3afa0a1cac5590ab6a923e35a2ab8db6410a9d33cb84d1c48a054377e" +
+			"549774b25f50fbb343ecd5db095155cce9fb0c77d09752f62d4bbf16a770" +
+			"30452a75f6bdf73f7807d8f3a6bae16ad06b22175fee60549c22548de9c1" +
+			"3df35ef4e7bf7b66491a62b93c2c3fb0c5edc51f60f5704b56af30f1079d" +
+			"7c385b99f958ef8209e030e381d1ee8d67d3cb84f32e030e8ea2c1d0c77f" +
+			"d6b242a9f48707557c8682a08e1127f51221a55c733ab1edd00a9c2912cb" +
+			"36dde85f73b524e1a4f4da6414c5e4c18d9537722b2becc8a91bcc63f2b0" +
+			"9f32409c53c2beee0de6726dabcd6bf33118a5c23fb9c5c1810476efe658" +
+			"4bb6109c516b45e16b2f79f96755680374d82b91f2c519639a1815fd485b" +
+			"a3c00b46fbefeafcf25554ec5a6a5ae2da07c85b8a0f9fcde50263d9ed85" +
+			"038b2f7aadb9de765655bd201235218bfc74bcad6a9ddf4506167a649afa" +
+			"df400b85752d68a92b7a97f26b334dd77fce824862046b286a7c8e0adc36" +
+			"f713a252a673d4d995b268badf4bec8b8eefe85c25b823b6728582d35c4a" +
+			"60041114dab72b0623b99e2758f6a1e97365279bfba0eb1fc8952ca4f2c6" +
+			"fbffd9f5fd7dcad1125b18a796981b5ead0b6431141315898ace96f0d38f" +
+			"865698df8822ca7b65644b6b1f0a0f0d2e5850d4c93ec48ca3eba1b919e2" +
+			"4413a46d595ffa427715e499db3b7b9ab53c64abec7302bc737a5bd124bc" +
+			"da756abbca132f7f67e6989e09bfb23b497da31bf156bb9c69ae54588df1" +
+			"7420e8fe989f0472c8893b2bfe57cdae265a8cc7aeb39624167a567a6fbe" +
+			"bb1aa30c3dcfd14f2808a070994085e6e1fa79021e77c399f90ab1f995a7" +
+			"baff672cb693bd39b798b4c890b7d0a57978d6b9bcdc5bf3f4d205f8f24b" +
+			"2b43d3ae300a96971c9182be297618b9adceebedba1ab0f324b01d23d7e6" +
+			"35f009db3dbbc643c2d787567594bc639bfd78c4f3e6d948caf06f013423" +
+			"eb3c764666b58f886d5d28137c053c2a28535efcea400147e92ac6753574" +
+			"3b47f9cb48852abed1d057647d5b1c6f334eab1a813401fccd3dae332738" +
+			"776bb223e359f3c459b5c573ba64fa945bdd66c5ac0fcbd53b67032a7b80" +
+			"25f551e8d1fd2a4291bdb7941cbabe3a09765dc263e2bbb6db7077cc8fe6" +
+			"790d4bed5e36bd976d1e37dfdba36aafcdaa10c5f3ed51ba973379bcb8fd" +
+			"203d8b7282abbd271ecf947e54486e8653b7712c9df996a8ad035f41f29c" +
+			"ab81509f922c67dacb03f25f8f120cb1365ab3c1c286849c2722448ba9bc" +
+			"ff42a6b8a7a52f2c79b2bfcbdd22ef8a5651c18879a9575dac35f57d8107" +
+			"d6bece37b15d7dfff480c01f4461ef11f22228792accda4f7936d29d4c56" +
+			"cbba103b6d3e6db86e39e5f1bb9e9fd955df65b8a6e44a148620f02b5b90" +
+			"b2be9e5bb526d0ec75b1e723e94da933a356d7ca42d0ce8349699f730b8e" +
+			"59bac24a6b633759c88041d29399ce60a2ca2261c7eec1acb9a56e0e65bd" +
+			"e37653ce2cf7eb83a4d019c755bdc5d685b6394ecddb9006823182dd8138" +
+			"a1bf79a32d07a8e5e8ab221995c714e571b40bb255b79e328ab883542c16" +
+			"4899fffa16eb3296f310e302512352a864fd809beaab4169113027c6ccca" +
+			"99a92c6ce35c30f9449a3add70f10db1ed08078e8e6cbaafef630aab7e9f" +
+			"c8adb09c18e33fe1af3620d1e4d069ac11325e23cc18e5519a1ed249caf8" +
+			"ddba871c701f1287cc160019766988f63e089bd9bf1af7e6f5b9002e3b6c" +
+			"264d69a8bac16914ab55c418d3a8e974677cdcbea36c912e90386a839a37" +
+			"77b878e680c07c7cc99f42a7dd71924babf7fb0627d1f2cc60d9d390d1e1" +
+			"50d47386be6eefec9ddbb83b28fa7e2fd28cc3867cbe42d13b00545af8a0" +
+			"48cc07016ec79808b180e0b258c564739185da754f2e",
+	},
+	{
+		key: "0d41cb4ac25217feb20e86fc2490e8d2ea2e8225c051252a9395cc4f56e1ae5a",
+		tag: "42df9f9a59d6dc05c98fd9e9577f7176",
+		in: "01caba7a19cdb09dc0ec6c522c61c628eacf17ef15485aa5710fed723875" +
+			"2e4e8e93dd4bbc414e4c5620bab596876dfbea33987e568ddabf7814b318" +
+			"8210a5f8d70041351e4d8410840642a29cc8d901c25fa67cc8f9664ea5e1" +
+			"9e433eaff7c722d0258ae112b7aca47120aa8af4420d4412a10732551db2" +
+			"cd3e0af6e5855d5eea61035af15a4d0d898d04033809e995706eba750a7c" +
+			"ac07aaa0dc71477d3020f778d0347f1a8e37c18540deb9ae967e734c0264" +
+			"df0e1f52b0b5334805579ea744c8784c3ae0c3ff8217cd3f53cb747f6996" +
+			"f3d2147699799e649061b205f97f7992e147fb20f21ff862c6c512e95534" +
+			"f03075e8e52f162e0d70d7a259e3618474427f400f44f75198edebae6e40" +
+			"a2173257d114e1bb5a13cf419c821eb124d90e89a938d91f4d2e70dfd1ab" +
+			"60446f1b602614930a329e98a0c30f107d342281db25b8f8259933e14d20" +
+			"8bbd991e42969e8b0600272f9bd408483cddfc4cb8dfe7bc19be1989c7fa" +
+			"129d38e1078d094b82e0a845040ddd69f220dc4aa2b236c44101d7da7779" +
+			"9827a7b037561b51e50fa033a045571c7267af93b96192df3bf6180c9a30" +
+			"7e8c8f2b1d6b9391767369625015da02730ad6070df4595eb8099bd8e484" +
+			"59214310cb62c3a91a4fa8ac3b3d7b2017d4254fb465f0a248e1bf45819b" +
+			"4f0360f37c9a79d405e2bb72e5c25a1b4df192cfd524d61e1e8b274f2fe0" +
+			"634c73f0653c7c9e9062c9d081f22a8b0327897eed7c6e870f2815bbac8f" +
+			"585c1bd868759a98dcb5c3db2f6c53244b9cc494a56f28a9ba673167cea8" +
+			"b799f37049ee7b0772972b3a6603f0b80eddb58ef03f916106814d72f000" +
+			"250b3573c97c5c105910d79b2f85ad9d56002a76a1f43d9d1c244ef56d3e" +
+			"032a9bab95fe3bd5dd830ad7d7e341f28b58c0440658f7fc2ca98f157708" +
+			"1c647e91432cb0739d9acdbf973ceb9b0047634d695279e8837b04dc5357" +
+			"f013fde3c55c9c53bf1d817ec59a1b18ed0ac0081ed9bbb3bcd1a5d3634f" +
+			"50f7506f79dc6a4ebfa640bf65682fe9aeca68088e276937669250064de1" +
+			"c19ad6d5c697f862114d0f81d2cc52be831ed20d3aab1e41fe6f476b5392" +
+			"af4799392464c51394c2d1a8325ee2e84f1635d295ee663490e538eb338c" +
+			"7126a8e731ad5c0becf144c7a9cae5c6493350b589385de29e1a0ad6716c" +
+			"346ec4f0a31ca5ea35c59ab6b099f65d7f0b3d00925a1da1b5777c029aea" +
+			"9679e895d7100645dc83f81d82a6174beab2357f7888ea640900cf3ee67a" +
+			"e0724a123919d78e70e05288f67e5e69ffa6f345be8a96e58bbe260184b5" +
+			"ec5c0c1354cfd516ebdb8d420029137d41b029641959cc07fa7b4e16b39d" +
+			"17f36b2367057410a42e0550e9ec1dcd2df4604d52d4f9dd1140d57af08d" +
+			"50e1527dad793b6d649324de799754f755818bf10e6d1ab614958dbb24ac" +
+			"8e2c01270a90ec3df4379c3f509b5ef721b0fd4f91a1bdb8127ae4dc74d0" +
+			"75f6cd8bb28319d6f8e8d8ff64fb4a42d646e9365156c6bc72cc46e9cd1c" +
+			"f9e735549e3df9a8e6b5fe541948b126190117db71fd1d61ad84be0f725f" +
+			"20b99eb141b240326d399976c4f2ce5823d94649a9580e1e8820bf49184d" +
+			"fc34378a60bea89b12aca69cb996c17847b7fb517cf2d51f16d78e3875ce" +
+			"aa33be15f6a154004f0e1134c6652c815c705efc34bcf35bd7743d28f0a2" +
+			"77d82dea4709dab41fbfb4e0cbc118c17aa00808872f0edc6437c357cd31" +
+			"74a02aee61890464e03e9458853189431bf5df6a0ad5d69951e24be7f266" +
+			"5bb3c904aa03f799fe7edc7bc6779d621cab7e520b5994f81505d0f01e55" +
+			"96e14b4c1efdf3e8aadee866c5337c1e50066b3acc039c84567b29b7d957" +
+			"683cadfb04fb35402acaba631e46ca83dbdd8adf28e377ec147e4d555a21" +
+			"e6d779d7c5a3078ab72702234d36ca65f68bd01221c9411f68f32e16ef04" +
+			"99a20c2d945fa31b79d9965853d38ada9d48eead9084d868c6bad974b0f4" +
+			"0956aa0fcbce6dac905858e46c4b62c0ee576b8db7d484a524e951f4c179" +
+			"decfc7d6f619e86dee808f246dd71c7e0b51d28bc958110d122fa2717148" +
+			"77823242711632f6e1c7c15248655ced8e451a107707cec8c84929beece4" +
+			"efe5503d3c1763d0ab7f139f043e26027d5e52a00d5414dd98a324a8fc2a" +
+			"06a1345cbde747f41099c3377b86bbdc5a17c8f6e5b773a761f78573832e" +
+			"4359b143810361dedc79142fffc49ddc0b32f225d50d360ceec3920fb0ba" +
+			"0693b644ee07fbd1ce829e223a02794b197614061c4bfa46112d105c2b7b" +
+			"4efea448501d146dece44f6640d674d5749db498b32969de6e165e705a18" +
+			"2aa1f3d8e16892b0120337640d52c9bee35e5b4b17f03eaeb31205c8ecbe" +
+			"1ae1b110023016e40ee87370a65c5c20bfb00f100d3c6c1de6e4a1c90162" +
+			"f25bddbf300ed637330206788a4ff96903f971c9618493ad074412af625c" +
+			"ff9e0f8f183bbd5e96c1f28307e6cae8b50cc0eb1a3a8154e44e9de947af" +
+			"002e4d1098d6b0ee3f2e71a10d03eb444729c42461283f37be8af2ce81ba" +
+			"bac246a05c2c94efacc43f0cf9ff3df38ab6fc1648c796ae7026ea95752e" +
+			"b70873a6da59da10d8b5316126431c4a17289466e95dc739c061d7a4b13a" +
+			"450809479eef421bddcdade77a6df133410328c754af8999a09b1a5c056b" +
+			"ecbb6fc2c339586ab92100f46d2fa1fa689994b36aa70703d76bf7738adc" +
+			"f0589fdfa6bd215339ad69ed983f62efce0add5a63fe7dfe4bfa006ff16e" +
+			"0cc06d39199ad60adcae12b75ca98d764502a783373da3a41281e03c2037" +
+			"e1b3ca7f7eb60e2b67427e97ec72d36670db7662c6daa505701fd279f116" +
+			"ac0ef569471f204e1531c25a4ac3ce19b6f68a8994b6f89b5abf034a6507" +
+			"32c7fad4206eb4eaa7cd9a710d866bf3c3f13c16faa268ae0cf4f69be909" +
+			"bb9b79aab80dd25101d4cc813a48d3f38d870f10ac0b6768005aa0e69e87" +
+			"dfc0424deef06414c9ba6f498c93c41c692a7a6221fb5595b390a32c70e0" +
+			"2cd64471c797ee8a143725849c1e054ee2043dcfc0b4cb1c00be21a14be9" +
+			"2d9a07f1b4e975d4c86b8a5c1387e6c42bf393e078fe86d24612d497e14b" +
+			"874485a3cc922b5b6d91295d7b79ab8bfa1c7f64b51e761d19bb9da82a5a" +
+			"a34aa469699036b6b2c55e2b84f84942f10585027ab07e2e0e562e0fc3dd" +
+			"36047850ded84be4416e22aa41c7a2f7d4a4d8e3dd420d746a1d8d56d87e" +
+			"5133a1b4380bd9a89500fd6d7e68a1ec02eb9e79e4a13edfdde1273466e4" +
+			"6b0e6a75f59ff6175716629da52463ad21de27f40fa2e25a566eec4b2696" +
+			"4af3a717dfb0170a73144c0bd9b00bed67ad8c0a146eb5a055812d071209" +
+			"c9d530cd4f50a41488c2238898dea8bb36b0f1496d3ea8c4ff8e263b367f" +
+			"64977679e697d88e5295bd97ac16a0420850d1ead9621e25a3f58925c266" +
+			"ef5246488b1c15a8fe0d8ec4291864faa5a67b2388b7786f47b6d27e8fe8" +
+			"46f85f85163e54155ef95cea4901e712a44404a4d3f27f28dd961ce36b84" +
+			"f3856770f07f20a2ebd34d77405beab04ddfc09770167d7d6340f494dc6b" +
+			"7e4c3df896bd974730193b1e862b58d4a5938e6e4ae8897dba8812924379" +
+			"e54f51a71364d39f76e24fdf2c6c704479ce85b456558ca6947b8fd76f03" +
+			"78273f0a7bcd1d860ef1defe4eea8fdb81c73eda028d82fdcb2248582ac4" +
+			"59eb7698a811e6c5823be886410f6b8577ff2e8252343b6ea890016ae846" +
+			"01c5894cfb988121059fd9c8fbc1596da470a149404fc67baa15383d38cb" +
+			"d17ac107b4ff3c1ca4c76b7930de02b240e7547d39f4978e0cc1fa37f8c1" +
+			"012b677f07bb4df4486196e9b0beb823a3827585475b878e3f6f0a2d3836" +
+			"2c7d34f9f3c91ed46c39cec95c2a0b6f0279a03a00ed5035b0725c393849" +
+			"cdb1ed3c0ecbcf3c2ce108017f468e1c3d469c03e8231d4195344ced70cf" +
+			"daa667252cc1554dce8d0c54eb4cf4da62367d77d7dcc02f81e788ce9f8d" +
+			"d306ba1b48192359cfe92bdbea9980f87ea0677d7d2082205a436cf514e6" +
+			"fde5eadd21b13dc836ce33b5dfb6118bcac79ae00fbb16d61f00a923b145" +
+			"f9caa9f3a2c7f0104f8b052e390987e57c8dc80cd5f0358afb0111af1fc4" +
+			"e31f92bd832ad35fd2e0bdf768272de52ce0b152f74d43a8973ad516b3ea" +
+			"f5937ec8a236ebc86adeba610de0cf7168453111f3c983b64df07678cae0" +
+			"a75466ae15adfb127328e716448cdbd2c1b73424cc29d93df11a765441e0" +
+			"0eeed72228e1099bd20569d9d0e9e5a0b3c11d0002e2896631186483db61" +
+			"c1a0cb407951f9b1ea6d3ebc79b37afb5a7037e957985e4955979b91fb85" +
+			"61ca7d5e8b9cdd5b7ce0130a880d9241027b011fea7696b0c695d4949ca2" +
+			"d0cf22d44b9fee073ecaef66d4981e172e03ea71a6edc7144393bfea5071" +
+			"2afac137f091bae2f5700bfb073a6d57fddcba674a899d7349044a10aadb" +
+			"2e7f547887dd2f765f394de5dc9ef5dbf1eab4d869be8cb68aad8e2614ac" +
+			"37bbf21ccd5a832ee09fdd07ce50a580a2af36256b1046e646fe3dff6d20" +
+			"0c5110f1ad1311bc39b8114cd11ecdb87f94df43d4f6468932fc0ed892d0" +
+			"3d8f3db3f8323ebb29776ab7d260493a36700bcda668abd62126a8189e91" +
+			"df2d2970ef688d4e8172fc942e69ba63941a36b79ac546fff38f5f7d1176" +
+			"57612a662ea38134e1090c3e903c9adacdeefd3ac2a0467e9f5125058c19" +
+			"7b2260d2afad2b0e627a9ae52cd579ee27168065658089e1b83a2d8cdb47" +
+			"e08966e4ec0018e78c4d267f9575b8fea2a42de5c2d25356fe4b8c9cb1ac" +
+			"daf0d1af4bf58b9704cd4bc08471e3b9a0e45a5693433ede2eb1374bce44" +
+			"1f1811cdc7612d7bb61f4f34aea0a44757bbcc12a55c1ba41a7901eb004e" +
+			"689587a38e5b4df4574ddcc7b2eda97f6e480d7d39f45247ea3b03c90a93" +
+			"0dd168b65d52a59ce9c2cb4e860cc6aaa0ee02a58d0c8ba990194bce80fe" +
+			"8c34ba5693fb0943ec2cbfc919e534cc47c04f502b6c217c2f860d1d482a" +
+			"a016aa02adfc2bea3171fc4e27e2a262fd37b824099aa227fccca508f778" +
+			"b8c6ec7aaff1d15f6497753f439daa9e52060fd6e9e056e6843d770fb057" +
+			"6d9e2e782db4843c0c2c7f408a17376719a3c5cf9fa08f04f8a779885a16" +
+			"5cf93ce404be",
+	},
+	{
+		key: "ddbd5d6c5ebd61fa72b453dd849dc302c98a0f3e300f4768bf1dc698a3827dd2",
+		tag: "af608b71a353e63c64911558baa122f3",
+		in: "c67e2524b0de16483158a0232078fadcf611e4fbdb9e642e397b21222423" +
+			"cc2ed42ed34ffcb178448919ee337eff9d7d691f622e70fd3317cfd271df" +
+			"fe6a9d9b7e07db0d20813e2331164a654386db2ab06ae2983bf2460eaaa6" +
+			"3aa0171fb87afb82e85b40d95c8993b2039d32e9d38473dd13f41fb1ff1e" +
+			"261752ab004b221a4472b9b1a0e139f0c999f826a26a7e7df362b0611aac" +
+			"fa83c55cca2f7c0138d2c30313c2f6eb357278328ea6ebd6a5077947e18a" +
+			"a97c34b9dde3b6f2de4b83778ffcebc8c9cb58756691d5e2a3d15a759a2e" +
+			"5050b6da937a6f5551aec069a08027d60dd870d175d2a5b5f0b4f3143904" +
+			"7445c368a5c866370e9426abbc1a1c5a272b96731c4128aedeee93e8e00b" +
+			"b450601a6d31ea279b9450e738b4a47c0dc22d2d8ed5d44257f6318e0c59" +
+			"b951fb6b57746062ab95cd73c23ef0a5c000a7d14c18bfff172e59b6f6de" +
+			"aa61b81009e803eb05e24fb0b706870e18889a9180ac16a042d12dfff9d9" +
+			"1b88130f045d2342fd5ddc5f443681c31090459f262d1a65654c55251fc7" +
+			"d5a67bd2e62940ccd606f3e50700e4d1e992a3fdf0388b9ce3df9de6dda1" +
+			"5c1cd6b70622ac062dcb7ed7058872c00ff3df94032853927126cf6fa4cd" +
+			"c468d91c9b52dcbc272fd7ba920dcd3ea1e048af9c3286dba74d988ce9ce" +
+			"77174e25a87935352721dc23b60a9549322fadbe6a00dd1197dfa25b33fd" +
+			"9e5713afcfd0fae6dbcf27147fa58d995580d7e0a903c895752fe9819f5b" +
+			"b002ed752719552d0f3575312f2e618173a8ae7c147ca64a709053e5d2e1" +
+			"2f4d1ea337afa9ac4f9ba62760046ec1e48f4ed8f6df66786c9fd9f5bc7f" +
+			"9ca2526e1327b042f4657c405757690e190c91f260dee2dd3d2e6616b721" +
+			"e489c7c3cb828478a3d953b88f09904e7927cdf6dbd6a5419eeeb83c0be2" +
+			"51934a80dfe61e09442f0761aa2d013e10aeec3a32df204571ce8984a430" +
+			"9bbe30ccc91977790bf0305d2651ee450b749c3e7761534e45970e70a0a8" +
+			"473cadbc88f096970c275f188c9d2644e237fd50c2e24c1eabbf7578e80e" +
+			"6500762ac513fcd68cf6f8bb7a9d9eedadca059d9ecec07fe6fe7792b468" +
+			"9311861728dd482f087c28374cf9c5ea20b2c8630029e8485fa6fe518c74" +
+			"ef77d44eb7526ca764e50b5f34ed0f253a91fb2af6e59338e2af6e041e01" +
+			"084e1efade1aebb7d1b698ccdb8b4248ac89cd40d9517d840960c08f5e86" +
+			"88d8ba2b54889c1870d315498b70e0e9720f2c8c53a3377a8c0bd2d6a1c6" +
+			"f17c6ff847eb14def6855dc3886b99039e528b421ccbf6064e39263f8f3d" +
+			"340d5d20b1b14c264ac2310b5f3a0c6f0c1006d0d4f1a69af68d28ab447f" +
+			"cd17387e1fc98f164982a6d05dd32d6b4f0f1b04e40c6c6e0fb4467dd6b1" +
+			"0c5a9c92cc8c2bc97ef669b6d55cdd0aa8a15c46af954359165949012713" +
+			"4ea9f74181d54a300d3172c9f01db73288ef6a709c763a4891666d0baf88" +
+			"8531dcc77f0911412d096aef9033fa36b5c1ed283b8b5c109e45b5cde911" +
+			"6f3da2533fa0ab81929bd5783271d5501a9e4fce2aff9eb5a70a4215b253" +
+			"46885d7e4225fe34bb55b309a114a312693d60ccc61267359a8c2dd28141" +
+			"226e7cfd99f0f12c69df57d75dd790dbabfe3145f7fd1a24fa58e03bc2e2" +
+			"6ea19288af4929e5acc517d8f52a074745ff4644d94179eae6ba7d267292" +
+			"bbd2053167a0da9be5e4b6cd0a4200fcac5182d9957dffbefa857e662b82" +
+			"fc3a7cc32506e78030ed5c5d448d7f1b4fd854a735a0c50016bb85e6e716" +
+			"0f87527bca0de235f4b7dacb75be84919c15a5b8cf6bec035795cb67061b" +
+			"7855c2134c1b1bfa6affe04b7db239f73af6ea9c02bc9f7972b7f6400b6b" +
+			"838f4653aefc42179c21765e3ca7a5e96b4402ff544d4bc2332756a23500" +
+			"11241dc42ec6848afe127c00b9c333e69bb5a54ea5c7193e59ea22bd6d32" +
+			"af4f56b1bd2d5982ef7d9c1b02d7668525e4e81b68a400f7afc2653f0f41" +
+			"a03e11c7a02bd094830093481afbab96397245b9f37a568ea1c4ae248cdf" +
+			"afc87f88b1fb5dc300d8e9039af4e6e701b458ed3f32d693f2e869b76bb5" +
+			"1358cbbe5b5089013bf452734388a176cccfc1ae9b7cff603631ca48e129" +
+			"b5c9573d4e379547272cce8aeeeb407d3fc57f782a0eb5fcbd41e6fb13be" +
+			"7e4f1067cd407b42a6121b2969c384916ba2b32563e659f52aae09c8ce2e" +
+			"3c500fbb7e58be74cc1592dcfacd9f0d4cea1a90a18658147c81cccf6fb3" +
+			"078ed27f369e7646f551386a74e1b07074d93e0c1f298c761af46cdaae9f" +
+			"f4be86808b66d0e228016d27a3a77c843365cb847fddccb0bbcfb3b9008a" +
+			"1bacac59ffb0aa759a0568c72c556caf0ac1091431b574687c5fc7bd486e" +
+			"963e0fc3bdc828d988734a21070747c955cf8dba2df1c3a0ba8146cd58b5" +
+			"91b6d54712db67a9851b1607c8445bc97406eeb7488f5f85e547850d619c" +
+			"407f97632ca1801f52c09c2b314b4ab0f8e7fb5851fd60852f4666913ca6" +
+			"bc840c1ec8f8f06caefdbfbf02ce00f20b87b14ba9e651c80f40a31d0306" +
+			"403f541776075fbf23733a6b19e3b44d04b455b29ef8effa70cce0c59331" +
+			"7119abc07aa8c8d0246a760b0b36a3d87b244e83bae8a745b8277a531298" +
+			"f5d0283498a509c89898ddf0f7a7455be1f8a6889c46d323f1dd18c3babe" +
+			"1751a05f871f0639f50967afa46c19cb93d9c2a79c81e2436a7a62f225bc" +
+			"37c90698640f5b43673e1dc276de05ff1e29acdb4ace5121659db5f23c49" +
+			"57aae22f53e6f2cc935824fbd07c2ac87672eeeab895c3f06e09e178560e" +
+			"2fcfa7097f10201dfb8b1ebac08ca806c1b3ba3aff9284846a1a3beada53" +
+			"e9f7ade12eb89b5591f462b2543bb4090e081fee9fb53bbf821dc92d6b16" +
+			"fe820ab2ee4b1f6c0b6a6f19edb0bf6479e257fc73bcd60dc2261d0a4752" +
+			"e23a0be18abf355f3065177d8c3c14e21edc178d0abd1b39f703e6335131" +
+			"ec90cba3d9846cee7354a06c320a3f61b8a269abc7138831614f57ca6c19" +
+			"a4a621142889cd924bf4ffb82b57f871b854f3157e8874c22d43a5726900" +
+			"bafbb8f2260a1eba3a462e23d4def2ccf68ebaae8e52739a1ce67c039eaf" +
+			"9a6c3232fbb5a91d1e59a8dcd3798ba71345fbf83d09b83b41cc49d5ff5f" +
+			"2e809d2b1d5fbc1e7001ea76b9b2d8f896eb6609e2e1c5c562d2a6e74960" +
+			"2d67a0f6b43a201d5087509b8dc7b0440144e308c18ff8b96b607de2f20c" +
+			"6ee99bb05367a8b25947011889f724965a2b5c52c9db1e0622df9343c548" +
+			"d054699badeb15fc41055af0d79a2bfc1a5b4574634fa0dd9dd10a6213ed" +
+			"b6991187dc560facdc27440456a0a209fd7f5ee4fb350ae71f869723e5eb" +
+			"5338e3d1448bc993afca6957f4cc7b047a2c7c9593b7234725e66cc0eb23" +
+			"3824eb4cb905701cc522ec210950b871397c6c0bb3d0b839f2eb1a120f70" +
+			"36107246df4dfb2c24891bef0bd1dc131f2c9d7c295ee967e3184d963037" +
+			"fcc9e0b8c7011c8e04b4e70038150d34caab4f8c0230418cd2d8a91146e4" +
+			"4e11cf6707452ddc03d9b4e6380658135dfb48f62c0690ebad75167f4dd1" +
+			"c0df3ed555b5081a7b82616d9e501757c83c2193d0f640236d59f9c97a4a" +
+			"5c8bf532aea2cf5964ed2dbd8a70c01ca5c7677224cf2a37f3b24d8fe4ba" +
+			"91cd3b5033715de227de51deed15afb8eda9d2b9615d197b8f98322d7096" +
+			"79c5131eed48050fbe0145a9284e236605c25a4876e2adba42f4e35a8949" +
+			"3d59bbf44b3338d9d2e65a7d7ec6c863cd47cae9e23181b07298078a5e9b" +
+			"06a5c7e1059f474eb1a4247e8f02cdd4efdca67d22035b12abecf9b15982" +
+			"de4932a28e797bc4de38442cff2cba263eeddba0ab14fc706dbca04eaca1" +
+			"b4cc13000a10e35b32461424809b299798e4d8e66c92aa3181c5df16ab65" +
+			"9611cb625e895a8021af8c60960227d6f2ebeacb17b13536a5ff139734ef" +
+			"37cb67018ef9a410b856e6f6eddbe3f59b088d538c50a8f3f0912d06e47b" +
+			"88d773069aa759cc614e1f53cf6e572c127123d1ab56b79ee753a921cb22" +
+			"a60e4e6cae768c9966de4e2625484f2e990154da7fca84b6e6c0b59201e7" +
+			"fb8a729cb20b4c774381e84f1bd6e304543d952dc76ef741b72f3a4ca7a6" +
+			"ea7958b8b6337994ed82dcf988eb70f509610b9a279ab4d0f28cc2b2dd99" +
+			"3b8637a6be0cb4b5f67c79654c6b15e1b61120374ba9b974a628c547f11e" +
+			"52d72d39f8f9c5dbfc23a89f22d38984dd8d5c3ca72cd54e6adfe2b3d163" +
+			"86afdb50967846a4c311351a51e5fd322757bdb061d44c8796a61fa4db36" +
+			"793bc11984eac83bbcefb40d0bc7bab0ca81e7df3a7f58c6fe800396716d" +
+			"832acaddff6d72c8e19dc9ea838294ead800deadb6bc18d3e399fa76c46c" +
+			"5d88ee72a86a87399423b0578eb6e27d78156ea2abf6f08b5cbf747f2f74" +
+			"5301b694bfba84bfe3c5527acd50660eea5105a2644c1aa92f954a604fb6" +
+			"a1b3b2d0331497deafc3aaadc7040b9188a36cf607ee85a0655ae963fd32" +
+			"91dd58f8bb50b4e46dcf7c2957639bffa6b12d895660dc0323b7a092f999" +
+			"813380b820e1873c60d3e3038129c66d507862100a5d5842150869e7873d" +
+			"6bb6ad022350ffa3813aca26c80ccae72692bed9c77c9d4da23178c57153" +
+			"90b5f4505240a796ec9d10a7f280bd60a570b1b693453807707651fc0464" +
+			"03e4768965a6f42f112152942134f0a38c84137c7a6e086ef1ab9ad20d24" +
+			"3b93356b305c0996ab7d02c02c44cbaf8f7e60b8c0b8c9fece3f189b099d" +
+			"dbd126b7357c1c4ea1c8bc1ad93db91ea9bf043a4320acb60b502bec37b8" +
+			"6b2a5004b8225e549e613c6f83b97b7e4aeda1b013e0a442d7ce2f14e78e" +
+			"a94bab700c9ac0abba945e28f39fdadff223c4498cb204f01ddfcb450a41" +
+			"f32ae47f99a49114c6646a5cb103e9cd75f9d81dba417e48c4053e3b0295" +
+			"2267cd30589b0f5d993a5485a6ead1ffab9f2f4294c5853ba76383a326a6" +
+			"a42fb8b78948aa49f0f1f614bd0a3fbd2a58a3197daf2094605bd838285a" +
+			"1260f1265dca74aadd95652632335fd17cafcb73b202c3f0e5da836c2dcf" +
+			"2934f005935dca80154af43fa34c8ba440d1581b74ff17dfaca369dc9aa6" +
+			"734c03916d78e1b952691cef918fe033d33f7f4323cf724ffb8cd6c219bd" +
+			"046e9f268eb0601098e93daa59dde370e46269dd7c54891f71bee2829a53" +
+			"df86a2c7fb1046cd7c98fa21cd83597be554997a70acebe0b6e60f1f7098" +
+			"6f65adcae24385cb7102bdd3e01300ffd15d00f9764b3a5c51e35e5c9cdd" +
+			"da84f4b656fe514ec4ff8dcd774373f8a9103cf36abefe875f7084b9bbd9" +
+			"42e0c997ec2d860a4b622ff1a39a628582fd81f237d3d8f6843d26ac77cf" +
+			"bd48003e8e8c591ff813a9a897e3149ff0297ff476299d717e54d885cdd4" +
+			"4c3ba6ebf54bc7a1",
+	},
+	{
+		key: "b15578da1020f662ada0ad4f33a180d9f8ad4991b3720bc42a22b52625c7414a",
+		tag: "b0e4ad4a010afd6dd41ed82868cda555",
+		in: "6d2afb7a9154064341bdbb533f11990d4987e7c90fbfc0167c1e58d6efff" +
+			"6010f7ed569dac62ad37183b0d384519ebed0bf9c6e05a070b4858e6b846" +
+			"547ab5e45619c866f83cce83dcdab6a8a6c36b115ac832de1c6d433b94fa" +
+			"35803fa1a36f1ee114f8632402a027a74ac110394f32ec4006beb0057f09" +
+			"a94dada8bd0d1ca9a14b1f2efb8f526d79d6438bbbaac0ca1a43935627e5" +
+			"d129d52c06bf6413af07513bc579447eccc3a9406645c94dae59dab98d6a" +
+			"f92fa90fd4efaaa4bec466806ed401d2083cda587139ad7e9ee2adbb1dfe" +
+			"a88b59dd788b954a0f52c3854a3fffecb4bea83debbb2f5f8883e6415d3b" +
+			"ac1b872df1afe185468adc59364c173082f1dd6da9d348f5f5ba2d216243" +
+			"23de1f623eeec875bf31d12acec40dc0c1b9562826f3105cdad4c43cf45d" +
+			"829aa8b14012c47847aef7a2a6e3935fd972235f5d3a7ce4ad3582785393" +
+			"602e2e27329914021eff38ed2926c88acec1551f17a1b818fc1c3ed4b3b6" +
+			"6825d55bea269d710123b52e12ca9520a069d9c6a21df3a0253b3a4a6a8c" +
+			"dc226d667541548834da6bdbbdc165f39e40047d4b647c507d981be17b3a" +
+			"836063436241a8bb46b11a2867b621413c42d838e4578b72cc1982e34bde" +
+			"c303b5575ef4b8dd9fea8ed5bf69539413909d03461d3853b5fbf714a61c" +
+			"769569f42b38fac4b849104e2f2ac1dad0e388646278789f83e0b0511571" +
+			"019d3bfc5b03ca4cb5564e4e75e103ea1b6000be6588e27105d7cdc2d2f1" +
+			"f680ad34ef823ac4bd4068146e9997834665aec7dcc7a82ff28d85d52dd6" +
+			"9c18dd35f326bcf709f74df5981bb90ca8e765fef9f0698a19e12220b287" +
+			"24a6d9e4f4c7ce93f8ca9a126689ad1df820072557ce3db246cdf41599dd" +
+			"44ca841bece6c7869358005536e1189aa86b764e890ef90970d6e3831def" +
+			"fa890bf8692381123924e7d9df804fd770a0a30ee97d5dcdca302833efe8" +
+			"1d4b2505b17382f0b3429b38c41269ac95e36e9f5a1dbc6e6c8963741917" +
+			"02a23198decb4efe6809fcbeb5d0c9098a4c300155dc841610e55c8a6e27" +
+			"2a38a39de3d8ebf38a750af25836ffb1bb7822bb98886280f0cab6838c01" +
+			"cec57961bdc2e1bf158248309ff9294adcb962252b1c24646d132a3be2c9" +
+			"1ff82e8e101facbdb807826cc9d1840a90874ba08692e808c336c9d280ee" +
+			"f36a43a75c746fb864f85711e802546ab5cc3f8f117904ba1a85d6e4b729" +
+			"85122c5041891e16d55b93d6fc1b7fcfdc80ed3d72d55d64b8895bbf2f8e" +
+			"d188684e7e89afdc1e6a7ab9bd1d3da95d68698df2cdcbb2e1a4ae70e2fd" +
+			"dd4760f9e5cf4255eeb1e9e8009ab507395bacb8b2177e7c5757ad02baa9" +
+			"a96db967d20a150d2dd7f3081d90675fe0c82f94aa3cfdf6ac5585583901" +
+			"7a8e122170cc817f327a3c8ef44acd6e4fa81b73bcd0bcb5792eed470481" +
+			"152e87f7a20c3f7c69d5a8199bf9bb7c7269b450dc37a9b22102acaa8438" +
+			"134d6d733d231cee9522f7d02fbb37b5818ad3ca72df4752230ee11392ef" +
+			"8f8219be55202bc3d476f5a9078b32fb63d42bed4cda5ef90cc62467bf5e" +
+			"418ecd9d5d0cf1a33eb9a930e652ce96057fef40b65588aac67621d651a0" +
+			"9003dbc3925912e385296cd3b2b386a44113308ddf2af52ca390487eb20c" +
+			"716b76d78ad45129e7c285d918de7107ea8c3b0cfd9e73933b87c0b2b505" +
+			"cb4c95794f2ee6d6d43e2e76026923a0bbfbc3bb22df9ad729452283ce62" +
+			"dc9b26684fd45e07650581afd73713a708869a069c58b599ab478974f206" +
+			"dbd3e4e563e346ff1881723c5fd440bdf9f70f761c6f746113397d7c04b6" +
+			"b341d7e44de7de0aae79badaaef5ed372ef629dffd52926110683ab2d4da" +
+			"a4be83eb86c8700703a660edd5a5029f66f1581da96fe1feefc970ab4086" +
+			"a83ae02e959821967bd27b3b629652f5bc3db2b7f1af674f9f3fb3a788f7" +
+			"88e6dc1722382971831a7ed72502f85b25888c1534d81c0a4f7351ecc40f" +
+			"4e0412e05718403fae5746d313a78c80ac297f1391ad389070410e1330a1" +
+			"b07d683d1c795bda74bde947f2cf0dc9638b5d0851cda27df030403816dd" +
+			"3b70f042888c9c192656cc4b9fea10b81b5347900d9199c8f0f47d42f2ee" +
+			"482b68acfa5ff47d9950c950a926a497d94c6a796e0b715416520bd6c59f" +
+			"30217718d5f1d7bf7c24039f6467214ac8783cf011b25c37c67dfddde426" +
+			"40afe97f94879f4586954737b86701b32d560f08caec3fc45184bc719c7c" +
+			"5bf699074fde814acae32c189158c737665a8f94637068322f0c23ff8860" +
+			"f1b1c1bd766440afee290aa6f7150c7adefa6d72a738cd2268da7c94788e" +
+			"bb39002e9a328a51f3a92dc5c7cd9e4faed5702d3592ad16217c4978f84e" +
+			"af0fd2c9e4c6f4dcdd9112c781eb41a9aacb0f7935bb5c92d41e67cfff6b" +
+			"991ccefbd667ffeded1de325da50c33e28e2eef2f636c9726dc5bfe753ee" +
+			"c7bb6e1f080c89451f81bc8c29dc9067ce83deed02769714fa9bb477aca5" +
+			"c09089934674a0cc8e4b2c3136b2e4af8040cc601b90a4dec898dc922ca4" +
+			"976ab5ae4ac5af93fa5b1854a76ac3bcc2090bdeaa49ec4f319cf7c7b674" +
+			"6d8e617abb3361b28b27983dd1b139ec4f5af7e116439d7ecb16534817bf" +
+			"264dbd8f59e80b443be12c17fa013c7f4d029504c9bb62b296c2326f4f49" +
+			"cc3201b70ac3f62abb683c630179594a6d4cf30fd55b163bf8d01986bb6b" +
+			"cb7050fd527f095c45661920268e56f760fee80a29c9d37b7fc23f608710" +
+			"1e723038e64ee1b91c4849d69bd95fc9bc24fc4a234f4855f2a203e3f699" +
+			"c32698585c83781677739f2c48697c93b3388dcc64aa61f01118495ded33" +
+			"21ef9a1c949481f96005f8d5b277a7d6a0d906ec304cf4292df172e72d20" +
+			"29ecdeb65f06267a605f376804bf7bc5b82d5c8facfe7e41dc10806d27e0" +
+			"bcc5a341d80b3c1532407f75088716d732632cd88b0037f0d829bf385fec" +
+			"b52a202956489f61f16b0f4781bf59068b33d7330571d0b4a6ed91830258" +
+			"e1220b308784fa155be9bc821f5c0009a33802fa66dd66d1dde997dddd97" +
+			"873ddf65927dc1be979af2b5f110eee627dc1e210326ac20544a757ac168" +
+			"1823f3dd04b1ddc4bf96677a0a87633994e7af2ec99b7d5dfe44c6192be6" +
+			"a6e69d17b074256da3947808fbf68c7506a7e2c99e6b64d1ffadbd6285d8" +
+			"e7e032e24d42dde0594bf03fd550be05e5d66c91a660cd1ab7cb1f43fa9d" +
+			"69885203a7aee35a28f117427d7ac02b742f53d13b818f8631081b1730d1" +
+			"5b4e1e283cc8e5c4fc3b4652fce05fd8db821f99fcf93e6842816a549791" +
+			"7f6c49cc53d733788b2fe3c687de58bfe6153c70d99380df1fd566a7c758" +
+			"8052c62e73340d6a9eccd2ed26b763d518f3a0c4d6362212fbecebb4ffb7" +
+			"dc94d29944fcc4ab37725b105aa7571f364146782356d8ef056a0be93a55" +
+			"0c890df8fecc178776fe40703ad1bd2443d92c420be4306d99686592c030" +
+			"fd3e2230c0b48d8db79002e8a832ef27edb53a45532955f1171203d38414" +
+			"b4692e901e9f40f918528fc494430f86cf967452f456b01846ac6a383fc0" +
+			"de2243c7d804e8643aabcb78e2653b145f400a999670217c8da43bbb9c11" +
+			"e074176424be0c116c304a420120138e901eca4b12ce68fec460b23bc0c7" +
+			"765a74fc66cbda0e503e7b1baf5883744e468c97c5f1c4b0acc4b87de9f1" +
+			"4b537405dfb28195439d1ff848d9cd28a8d375038ebb540a9075b7b5074b" +
+			"ebc18418a370f1d3ac5d68f5d239513002ad11bfc2b7ff53e2e41ccffc4b" +
+			"0503acc4967c93ae8590a43439b5e7987d10cb8d1957bd9ef717ee3d12df" +
+			"5d6736c1d8bd8da102337a94b7d14f830f6c403cbaf7925a8a2a7af1311c" +
+			"57224967a38f6ca374013a9819c55fd2e2a5fac4f2490be5b059f4cd9c60" +
+			"2d62f80789eb8d9ab893c7f44a4945e41886af218179dfa754bbb59aab68" +
+			"13b71d2202eb8fc8a425625d21176a28a620e21bb0dad820c0b7051ce8d1" +
+			"3a33f3af0958bb6cd89f9d6414ab00ddd1d2f9fdece9183d0c05fcdfd117" +
+			"10d250e4b2029e6992a88293d0457e73e5b1b6a1aae182c69b9cb664992f" +
+			"073595ef68117026ad7ea579a4043cda318931eee7b2946a34cdc7c9755f" +
+			"80cc79a2bfe3ed9c79dc52faa5126b824868c965eeb37e9e4e6a49600f3a" +
+			"cce93c0853b546edb310dcd16a5755f15b1098b2f59dbd2d90e2ea8360ba" +
+			"f12108236e854465456598ae2f7bc380f008f2e3cd7c98c87643cafd7c36" +
+			"d40e2597236428d46aa5b260f84b4212d5e26804086adcf00363ce4becb4" +
+			"9b57eb2847b2f18ec82c99714ad4ddfe4ff3bcac1d0fcaa32660a1dccc68" +
+			"5bed83254c8e2ea0ae3632a70cfbcbeadef922d78a006d43ac7ab1f8a609" +
+			"c6e0ebc3ca6bb8430f1a562f41010db74b9febf931ca794fa08d1bc17780" +
+			"532ae76f25c4ee679d788835dfa4e70ca154c9e2865c3750ffe7b837eed1" +
+			"972be058fdf2bdb3eb301867bb132306c7aa237f6771d60bbc56cf31cb30" +
+			"32a87204d454542de747418470025ab84935d3eaaca01dbbdae9ef6b5d3a" +
+			"ca62ce9f871a3e1272b2b671582c096a349c00f32d742ddb17993994d8ae" +
+			"fc178cbcf9abc03114ff2bf7db8f757c63d6898faccd822f5c2e9a7570fb" +
+			"9cfff148570888be24ae42644c1a5bebb6f6287147a4bcc01c7675be9e4a" +
+			"897519dd3132a7cc2e778f8c90d23dc8073f6fa108d7ef82d561794bd9d5" +
+			"f1faa306334f338ac3ba99c853f79c24f7048fa906fde87d1ed28a7b11c0" +
+			"66a3bb98f8d21055aaafdf7e069b77b60b3d5cbe7c5e4379c7651af955cd" +
+			"82a19a09caf36becb6cd3fe9e12f40379941542709991066df21b7b12dfb" +
+			"2416d83fcdc33bb583e3b42f24f53edf8dc7c579ad3be831c99f72bf9fb7" +
+			"a35b6562e824e039e6bf1adc8f5ca53846de7bae11c4317e696d887df33c" +
+			"525f0a9c01fc29f2c26c90b85fe82ed8bd50954cd4e9ac7c85c7f3efec75" +
+			"da1da4ed173cb695cee295190527edb3cb06c5dbdabe0228cc60b6455153" +
+			"76244f27aa56da2db10f2659090137ffb82c57233c833e0bbf22d6f647fb" +
+			"97b3652d2888b3ab08010b8e8a6967d560b747757806736dc98b78226634" +
+			"f1eecaa4a2e23ba36591acb5737d735c5bc7a2e36f1a46946927e061fdf7" +
+			"7a3b68ef582c26b01f5aa9a438ecc26c6941221d1590c838072f9e471fe7" +
+			"fd59dacb0d092d40d76ea2f7c6e954a132a015bd4cb31147f3ebe4518322" +
+			"916438a62836ac85a4cf4492190a85bcc8edb37e38b99ea552d749c30f74" +
+			"ca20c298165e8ed02d4671e0b41cac3a32a345b9349ad22c2a4bb2c16a4c" +
+			"e0613ca0f0518759f7d2b33cfad2fae764f410d4d9ff8a76ae02a8107e7e" +
+			"01d9cd0552676b85ba002f19c01ad5f416d1d08bb84fec7c3555b098dbce" +
+			"48e1a5d847895e54db9c5b80cc22d5b87cd41a1a94be102bdd45a3cda5d1" +
+			"181e10446d213d6b3fdc350d486d2011d705c5f16ccf7519065c47bad7d6" +
+			"89c71e5fdf9d04bfb91eb1f07fa0f001009c1d4b1f6a116a570823a8580b",
+	},
+	{
+		key: "392468efccff36dade31fc1c62eb38bb61394fe448def9d9d9beec2413ddb418",
+		tag: "e1122e7c8e6965b90addbd46d8a548d6",
+		in: "6a13d37f0ec933194c227351f4a19b507d93465b1f3e88dcb5f1ed1262fa" +
+			"58ea99ff31e6fc85c39c04129fa69195b71b2060122fe618dd9430a63f97" +
+			"54b52a80b3cd099f248f91a468bae211a27bdb47ba005d29881ea5143a82" +
+			"967c4c30c9a4f0dba1a4975e6407fe296d40023a00efa06be763f2d73d46" +
+			"a2901ae28b3d8ce18009a462e223b71476d7b954c138e177d15a390847de" +
+			"96a7f7fd0598748e86b0f08e64d915e67c7e3cf936f3dcd60edebd36e2a1" +
+			"d65b6ac29530c48ab3bd52d45b4f938a19b9b31e2911105a8561600d5377" +
+			"905a67112ec28025aa680350ff85b808c5b4c98b7b9567d03f5ed3911ec9" +
+			"365a8de4b15ca62adaa69e5ba710eb1756a346016c67a297d8624f9f1ab5" +
+			"b3fbce98b141049f0ce26c85d2f8a9cc6ca8ab6c6e148be968931430dcc6" +
+			"2bf58ea9698ef52a5d271cf48e6748ac9e04bc7ae7da205a1a7535478322" +
+			"d820eca146cedf4b2f9aa9fcfd77ab56a7276977401dcc1f96baa1b607e0" +
+			"256bd04ec324ec67a4313e2d5a53d3a3fb5332927929b20c63bde805f637" +
+			"eb1050fee2a152a0405634f55c48a59fe370d54b2ab1671dae2c7fd92243" +
+			"10627808e553127c74f724362b4a6ee49b697daae7df3ddc5d2ed9d6befd" +
+			"77fb9f68fe3041f6ef13f46f34ab682ab8563e8996344f82b2ef006a8d54" +
+			"3dd9c1db4979d7da97bda45e722065f8a238f0873217b783a9a629a12b3a" +
+			"4de437445039997bd243efbf5e3b6059b9459d395290efb9081c632fb694" +
+			"81000dc74c395cb507422df181aba20f776ce3fd8765ac485021992c98b1" +
+			"67c68805662cb4356a0ee7ba6bdae51ac10cd06bb5b2f3a72841c714c8ed" +
+			"bc56998fe2fefb9bf69e172fdf54b2ab138ae59372c52a67e93882a3000f" +
+			"d966992aa2250c6ff93e9cac89645d70625d79332ade5dab7eb1adbe7dce" +
+			"5a013fb65ad32fe22ed16fb9bb35eca1f37a0433c320e8752f8fc4b7618c" +
+			"5e4df2efece832e259ad98b895c474e47d0e3fc488bea8f717a17de0dcf7" +
+			"597fb8fe12e62246296f9a887dcc3a700820c190a55a4931a7d44bd3bb2e" +
+			"ab6c8a8126f1be93790cebabc1d69e01796e6cc80e7c16bbc82fb333fb21" +
+			"c774ab7db843242838e82d8e1cb8ccab385e67a4271fe7031d74b6e8edcc" +
+			"8ed585d1c05a365c7665899c1dbc561151d3b44bceace77c4f53c0e0f6f7" +
+			"74d42f9ad3e56f1c2a8d53879d695f895690afb4698472a3d52d67159313" +
+			"133c87823fe0500eb68fe286f8b9a2f59f12785d026dc97bdbf793c7d1eb" +
+			"155f1f136aae66c256583e987f718afbe733e0a5ce30d021493fb84e2242" +
+			"5b18754d126235ef80335004fa84f88361a584753df409360cd8bd45bace" +
+			"8f48156bec66577bf2c685089f5ac7e7ec76c0df068fbaa47661f8517f92" +
+			"e14723b3b278f151816537a7212c96bd340a00c15c9c9bc9a2a5d163655d" +
+			"84b38073e2be9217cad97d362d89d4baf3ce0a8d8562f19a8c97a9aaf5e7" +
+			"77d60456360ffb77b30f177d2809052020d141697ecf9cb65f42b9190caf" +
+			"6540b2c82f6e5a8482934a6a1a5711a8c24546cd8ba432068404eae5a827" +
+			"2e09efc3c6037af4feaac0a46329229b010ecac6b9f077a9b076bb6d9ce1" +
+			"38401eb38d124baa11507a994185295020bf9b754fcf78430db9253f5929" +
+			"87c46c0f8589c4e463b15a3840b1cea795e24cf6b20f29a630136e0589b3" +
+			"8dd7fbe5ea21da72c88bd8e56473586822aa3765660a45a988df9b8eb8e8" +
+			"141939d3e4cc637c5d788064d40a9f7c734e43fdf8d7189a5d76700d9743" +
+			"fe0122944663afdb88c5201318ca782f6848b742ddebe7463fd4a32280ac" +
+			"1cf8311e9137d319de05ce9cd85abab24c5364041c14d3b4ce650400498e" +
+			"122166eccc12784b7ac3b262ac0b198ffc26eeed9a5da5374f7a2a53c87a" +
+			"78c217ea1fbf8d38f62511657b73109f31691aef14d82ce6e1010eae9e6f" +
+			"a419e5c1c16c0cc70651eb3374c03549a1bc7d3ed42d60f886102c798dbc" +
+			"ba56f0a2b3b9b412530c35f5f7ed06311ee14571f9c26ed9c81ef38ff000" +
+			"2f5ef3aab7351e32049a6ef8f48a43da1d84402d229df513dfaf1b2e4043" +
+			"6ce68c70ebeddd7477c9164f0dce45a6fc5de050f52ec269659d5854bcae" +
+			"f7762ed7400713c27a4d523eaf8c136c4a1ca00b9e9e55902daf6cdf8528" +
+			"c22ca1f2fa7ce87902d75a6850e1a5a4592497be1bb401878f18b189b0e2" +
+			"c59d10705bfabde3cd2da01eb452006b294108d5d42e88e9e15424d8cd0b" +
+			"8ab43a6c546b3dbf52e47b59cde6a3e417b0395220b6d63736d429da3458" +
+			"9a2524f1629320206fa7f1d8a041e17222c4a5814561937e1030e6375c77" +
+			"9dc988bb928bbdbe2c2eb20111639725d82b5d7192cd3e4acc27581f0ba7" +
+			"286cff41f97aa5a52ea0083de5057fd2ba985aa738e4d03fcf11ebab1d97" +
+			"e2ac77d1c2beb8799150a421a07b3777d0b850f24194b8309135b13da6c7" +
+			"e38653a711e407a1811290fbb7bc15d8b12efc6916e97ead41e042a44721" +
+			"e9cde3388073d921595bcddcac758dc675173f38242e65e4a284aaa7e8fa" +
+			"6adddaf00bc46428ab2d8601205b8895bcedfc80ca0aa4619ed6bb082ddf" +
+			"33ec04fa5d417f33fcdd238c6b11320c5a08f800e0f350b75d81e3bcbd15" +
+			"58a1eab87a3c8c2ffd7ba1d7e754e607cf98ba22a3fc766c45bd6f2569b4" +
+			"84639e6611714119d188a24a5e963089a16ed34e20b9f154cad8ac6031dd" +
+			"7a3a885afc2ae5e003ae8d4e4aabdb3e51dfc423b8cf4ed9ae2010072cbb" +
+			"b1108c7da1ff075e54ed827a0963ac5523ecdf3fc5eee7b4d1a6773764ec" +
+			"5c30f41690523fd70d895edb7ca6a1806d54240c4c7b43410da73503a323" +
+			"90d9070ed30da3a2fb5eccd40d083be7cf8bf40b4279f819cf795b6f075b" +
+			"5a67a10a06a6076d0d83c72efea05f244901c4b5fd9eb380432519311baf" +
+			"8c81f6325df4d37ff4d30d318f904ebb837ec76b341dd00a8f247cf0bbe9" +
+			"6f3784dc8f5feb344958fdf1a9ececb105f8770826db1f17a5281e997951" +
+			"d3c60cc28fc3e66ffeb5dbac315f98f6d240208043f28dee963d843e68ab" +
+			"57d847f76ae2f96ce6e37f377ef5dfef2176ecd7440ce4dadcec2231b606" +
+			"e4a80420fb3ed135640e1f05d6bd58b8dce062dd7d36b885d424f6318e5e" +
+			"a0753efbb33bbc7360d2b5dfab3ae0d5e000b8d31f2ba0f5fd8b34f96b55" +
+			"28fff35e769461d0f03cf3bfdf0b801dcbbf2838180cb9b108e06c353e3f" +
+			"0b9ef61678cfed1ea37ae76bccb5ef5957ac2c8e8f4794c8145a15f1cc88" +
+			"bfb0881080326c481b373c3bc9b07a9b60a0c8bd5fa4f6f90145590a5227" +
+			"6fcc0ccc2375d0ccb571d414d1b0c38b4e02c39db4d701c5e25e90785ef4" +
+			"d26f35edd8c4b96455bdca7245cfefd9cfbd2f319615e5fdf07bb9564fa0" +
+			"44bb35a58391d02e3927780b4076bc0893dfcb4b63a32cd7a541a4a8c253" +
+			"0349c6e96e378dbeb66dedf87d813d0b744452c1c4088507dca722193827" +
+			"9e2dfa24e4a409de494acf654f44262db9206a7717fa434ac4fdc6a6eb5b" +
+			"1fd5a193b6043bc4327c8c09fd6822eaa9df37bbcac1077754a295621601" +
+			"267b68733b62dadc2563f1700af180141f29899e2689dbbe9745ba8477f4" +
+			"352921900b403a01c9dd042a8c1b0e0489959fb0b0a8431c97b41e202204" +
+			"212ebfa00c593399dbd14d7aec07b8292d2e40b48f05fcd54a15da4a24d7" +
+			"2759e409f4c7b5b98fce4abac6c30e4872d92efa1f96479ec30f21699825" +
+			"50fa60584f5a09051a00f8e7dbb3853e66ca3f05fbfe43bef9b120a25a01" +
+			"eb436ba8ecda715201eda72e517d628f883386c1503aa8b8e75610f7155e" +
+			"9f916335ab6d6f0f9589b6220cd2b81c2c937dc065d3d14a7df8cc916cd0" +
+			"0ce1bb53fd9c8974298d3bd316f3658aa8cc6904f073a1472149e4b08c64" +
+			"5e11abe0428ccb6174df2103edd735965d6454b543d3f01410f77053f65e" +
+			"c1d1aee56fdd3af23bcd4e1a7fcc4e600c4831007c33fe5f0c8300f686eb" +
+			"9b4d1e4f08fe4ddc8a90be14dc3a5a88ff96716509341d5db24c0d016863" +
+			"998b1859c5021df815a6f1ca9845f1a8e99dbad132b406227c5897a1bdf3" +
+			"e698962f799133ff4429decbef6ce036296facf38e4812fec102b76c6d30" +
+			"beba1b70722254fafbc471096153478c971db7d96263660209265cb10f13" +
+			"b34b5fd55c4abe818a5f9715d8a85094e2946b7a001b47f629e26c636d86" +
+			"4968ad2ab616dfe28840bd60b4b9855c8dbe1cb873fcbc4577b5fefeb8bb" +
+			"4832039867dc35db9c036c83bc204396e3474ddfe806c77c65c936f488b6" +
+			"7c1028739562d7bb055d21441af29ae2921290e548dccf8a56021385422b" +
+			"15da6b232b24151309a75a00296d11aa1952a1513110b0faa93d1d8cd9ae" +
+			"fa9f1c59377ec9165b2c9e07cbde40db7b81bca6d58fc28bae8f473cd0e9" +
+			"a2420e0b943a83d284108626c24ac570b1d6c1ab971e71f43fbd6c00e171" +
+			"238141a6dc987a60385c3a04dd147a2f8e80dfe727b104c0fdd80b326f59" +
+			"0b9f86fd7b2fd1122a390979889eabd803ab57159c8509a1443eb6789382" +
+			"090a770ae4eba03306f96e50e19a7d44c584ccc230d104548946efca4520" +
+			"d61de5f473e2f4eada6c8ce9c7ee975eb4f63c0483cb775ed7d3cf690a61" +
+			"7d6656d683a8512707d81ca5ba176a42bcffcfa692129f292607d2a47536" +
+			"ccaeb464c9272d6f3816074b712af602470088b253deba18771e5f67734b" +
+			"587707cdd06f35264b2262fd253c25b5d38ee7db287610e5398062b7a34e" +
+			"6e4cf7447d00873b930ad148fd96f0ab18771bc468b874bb109924101c84" +
+			"c4e239ecc7687d875e4d94a1a973620ca61e35a872c2e2e61a502169f1bb" +
+			"4e5ff5fa2bff657be6195b3e2c7151a52fc0096d98e7f08f5a98f570aee1" +
+			"7b4275f1356e87e080ce0e1b9bbabe7dea48b5903bc390ce23472ad64a89" +
+			"41c3247bfd23ea90b2dee09085571bad85568040105e098f993bb37e43c3" +
+			"e6d511171c77cfc450570dfb9fc6a3930ef43c03f8213f6203d545d791c7" +
+			"d3fa42d5dde1655038d35c5dfacc12e9dee24fe833977549eda68ae8b508" +
+			"be277e743921b584f9dfa0eefbd8bf3c23f51efdef7f7487001d29e8097b" +
+			"ba63289cfca743023d1668555a46fe6d5b7421377414df1e9ef135480622" +
+			"22e2e9a7baa618d88f407517f6317b6a0ba3384ace16d68631d59ea169d5" +
+			"092d20afc1a481b82be5e734bb092953a0a94702bae1a0f48d2a22b9a05f" +
+			"f64493b7b2e984f27582b1eb937fddf8512c49830435d146dcc291a4118d" +
+			"5dc638b99cdcbcc5860de7a92c5b13cbd1e01e051f01af40afe124346320" +
+			"d3626bf9d8f7850744e032a993c276fd388718237740c6caf260fca60b8d" +
+			"d846102e3262b6e05ceca00c6affe938fac1847350865fc858d3ddd1d130" +
+			"71d1221ce7c5d575587fcba580e544b74d877ed5ca92763ef0ca0d7bfa08" +
+			"d57a0216b2a01a2b9ec74b8430051e0074862b7be25b6766ab520f2eb75d" +
+			"eeb979c28f03795f6f1e4b8410beab19a20febc91985b8a7c298534a6598" +
+			"f2c5b0dc5de9f5e55a97791507bc6373db26",
+	},
+}
diff --git a/libgo/go/golang_org/x/net/dns/dnsmessage/example_test.go b/libgo/go/golang_org/x/net/dns/dnsmessage/example_test.go
new file mode 100644
index 00000000000..d14fb3aaf1c
--- /dev/null
+++ b/libgo/go/golang_org/x/net/dns/dnsmessage/example_test.go
@@ -0,0 +1,134 @@
+// 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.
+
+// +build gccgo_examples
+
+package dnsmessage_test
+
+import (
+	"fmt"
+	"net"
+	"strings"
+
+	"golang_org/x/net/dns/dnsmessage"
+)
+
+func mustNewName(name string) dnsmessage.Name {
+	n, err := dnsmessage.NewName(name)
+	if err != nil {
+		panic(err)
+	}
+	return n
+}
+
+func ExampleParser() {
+	msg := dnsmessage.Message{
+		Header: dnsmessage.Header{Response: true, Authoritative: true},
+		Questions: []dnsmessage.Question{
+			{
+				Name:  mustNewName("foo.bar.example.com."),
+				Type:  dnsmessage.TypeA,
+				Class: dnsmessage.ClassINET,
+			},
+			{
+				Name:  mustNewName("bar.example.com."),
+				Type:  dnsmessage.TypeA,
+				Class: dnsmessage.ClassINET,
+			},
+		},
+		Answers: []dnsmessage.Resource{
+			{
+				Header: dnsmessage.ResourceHeader{
+					Name:  mustNewName("foo.bar.example.com."),
+					Type:  dnsmessage.TypeA,
+					Class: dnsmessage.ClassINET,
+				},
+				Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 1}},
+			},
+			{
+				Header: dnsmessage.ResourceHeader{
+					Name:  mustNewName("bar.example.com."),
+					Type:  dnsmessage.TypeA,
+					Class: dnsmessage.ClassINET,
+				},
+				Body: &dnsmessage.AResource{A: [4]byte{127, 0, 0, 2}},
+			},
+		},
+	}
+
+	buf, err := msg.Pack()
+	if err != nil {
+		panic(err)
+	}
+
+	wantName := "bar.example.com."
+
+	var p dnsmessage.Parser
+	if _, err := p.Start(buf); err != nil {
+		panic(err)
+	}
+
+	for {
+		q, err := p.Question()
+		if err == dnsmessage.ErrSectionDone {
+			break
+		}
+		if err != nil {
+			panic(err)
+		}
+
+		if q.Name.String() != wantName {
+			continue
+		}
+
+		fmt.Println("Found question for name", wantName)
+		if err := p.SkipAllQuestions(); err != nil {
+			panic(err)
+		}
+		break
+	}
+
+	var gotIPs []net.IP
+	for {
+		h, err := p.AnswerHeader()
+		if err == dnsmessage.ErrSectionDone {
+			break
+		}
+		if err != nil {
+			panic(err)
+		}
+
+		if (h.Type != dnsmessage.TypeA && h.Type != dnsmessage.TypeAAAA) || h.Class != dnsmessage.ClassINET {
+			continue
+		}
+
+		if !strings.EqualFold(h.Name.String(), wantName) {
+			if err := p.SkipAnswer(); err != nil {
+				panic(err)
+			}
+			continue
+		}
+
+		switch h.Type {
+		case dnsmessage.TypeA:
+			r, err := p.AResource()
+			if err != nil {
+				panic(err)
+			}
+			gotIPs = append(gotIPs, r.A[:])
+		case dnsmessage.TypeAAAA:
+			r, err := p.AAAAResource()
+			if err != nil {
+				panic(err)
+			}
+			gotIPs = append(gotIPs, r.AAAA[:])
+		}
+	}
+
+	fmt.Printf("Found A/AAAA records for name %s: %v\n", wantName, gotIPs)
+
+	// Output:
+	// Found question for name bar.example.com.
+	// Found A/AAAA records for name bar.example.com.: [127.0.0.2]
+}
diff --git a/libgo/go/golang_org/x/net/dns/dnsmessage/message.go b/libgo/go/golang_org/x/net/dns/dnsmessage/message.go
new file mode 100644
index 00000000000..d8d3b034292
--- /dev/null
+++ b/libgo/go/golang_org/x/net/dns/dnsmessage/message.go
@@ -0,0 +1,2103 @@
+// 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 dnsmessage provides a mostly RFC 1035 compliant implementation of
+// DNS message packing and unpacking.
+//
+// This implementation is designed to minimize heap allocations and avoid
+// unnecessary packing and unpacking as much as possible.
+package dnsmessage
+
+import (
+	"errors"
+)
+
+// Message formats
+
+// A Type is a type of DNS request and response.
+type Type uint16
+
+// A Class is a type of network.
+type Class uint16
+
+// An OpCode is a DNS operation code.
+type OpCode uint16
+
+// An RCode is a DNS response status code.
+type RCode uint16
+
+// Wire constants.
+const (
+	// ResourceHeader.Type and Question.Type
+	TypeA     Type = 1
+	TypeNS    Type = 2
+	TypeCNAME Type = 5
+	TypeSOA   Type = 6
+	TypePTR   Type = 12
+	TypeMX    Type = 15
+	TypeTXT   Type = 16
+	TypeAAAA  Type = 28
+	TypeSRV   Type = 33
+
+	// Question.Type
+	TypeWKS   Type = 11
+	TypeHINFO Type = 13
+	TypeMINFO Type = 14
+	TypeAXFR  Type = 252
+	TypeALL   Type = 255
+
+	// ResourceHeader.Class and Question.Class
+	ClassINET   Class = 1
+	ClassCSNET  Class = 2
+	ClassCHAOS  Class = 3
+	ClassHESIOD Class = 4
+
+	// Question.Class
+	ClassANY Class = 255
+
+	// Message.Rcode
+	RCodeSuccess        RCode = 0
+	RCodeFormatError    RCode = 1
+	RCodeServerFailure  RCode = 2
+	RCodeNameError      RCode = 3
+	RCodeNotImplemented RCode = 4
+	RCodeRefused        RCode = 5
+)
+
+var (
+	// ErrNotStarted indicates that the prerequisite information isn't
+	// available yet because the previous records haven't been appropriately
+	// parsed, skipped or finished.
+	ErrNotStarted = errors.New("parsing/packing of this type isn't available yet")
+
+	// ErrSectionDone indicated that all records in the section have been
+	// parsed or finished.
+	ErrSectionDone = errors.New("parsing/packing of this section has completed")
+
+	errBaseLen            = errors.New("insufficient data for base length type")
+	errCalcLen            = errors.New("insufficient data for calculated length type")
+	errReserved           = errors.New("segment prefix is reserved")
+	errTooManyPtr         = errors.New("too many pointers (>10)")
+	errInvalidPtr         = errors.New("invalid pointer")
+	errNilResouceBody     = errors.New("nil resource body")
+	errResourceLen        = errors.New("insufficient data for resource body length")
+	errSegTooLong         = errors.New("segment length too long")
+	errZeroSegLen         = errors.New("zero length segment")
+	errResTooLong         = errors.New("resource length too long")
+	errTooManyQuestions   = errors.New("too many Questions to pack (>65535)")
+	errTooManyAnswers     = errors.New("too many Answers to pack (>65535)")
+	errTooManyAuthorities = errors.New("too many Authorities to pack (>65535)")
+	errTooManyAdditionals = errors.New("too many Additionals to pack (>65535)")
+	errNonCanonicalName   = errors.New("name is not in canonical format (it must end with a .)")
+	errStringTooLong      = errors.New("character string exceeds maximum length (255)")
+	errCompressedSRV      = errors.New("compressed name in SRV resource data")
+)
+
+// Internal constants.
+const (
+	// packStartingCap is the default initial buffer size allocated during
+	// packing.
+	//
+	// The starting capacity doesn't matter too much, but most DNS responses
+	// Will be <= 512 bytes as it is the limit for DNS over UDP.
+	packStartingCap = 512
+
+	// uint16Len is the length (in bytes) of a uint16.
+	uint16Len = 2
+
+	// uint32Len is the length (in bytes) of a uint32.
+	uint32Len = 4
+
+	// headerLen is the length (in bytes) of a DNS header.
+	//
+	// A header is comprised of 6 uint16s and no padding.
+	headerLen = 6 * uint16Len
+)
+
+type nestedError struct {
+	// s is the current level's error message.
+	s string
+
+	// err is the nested error.
+	err error
+}
+
+// nestedError implements error.Error.
+func (e *nestedError) Error() string {
+	return e.s + ": " + e.err.Error()
+}
+
+// Header is a representation of a DNS message header.
+type Header struct {
+	ID                 uint16
+	Response           bool
+	OpCode             OpCode
+	Authoritative      bool
+	Truncated          bool
+	RecursionDesired   bool
+	RecursionAvailable bool
+	RCode              RCode
+}
+
+func (m *Header) pack() (id uint16, bits uint16) {
+	id = m.ID
+	bits = uint16(m.OpCode)<<11 | uint16(m.RCode)
+	if m.RecursionAvailable {
+		bits |= headerBitRA
+	}
+	if m.RecursionDesired {
+		bits |= headerBitRD
+	}
+	if m.Truncated {
+		bits |= headerBitTC
+	}
+	if m.Authoritative {
+		bits |= headerBitAA
+	}
+	if m.Response {
+		bits |= headerBitQR
+	}
+	return
+}
+
+// Message is a representation of a DNS message.
+type Message struct {
+	Header
+	Questions   []Question
+	Answers     []Resource
+	Authorities []Resource
+	Additionals []Resource
+}
+
+type section uint8
+
+const (
+	sectionNotStarted section = iota
+	sectionHeader
+	sectionQuestions
+	sectionAnswers
+	sectionAuthorities
+	sectionAdditionals
+	sectionDone
+
+	headerBitQR = 1 << 15 // query/response (response=1)
+	headerBitAA = 1 << 10 // authoritative
+	headerBitTC = 1 << 9  // truncated
+	headerBitRD = 1 << 8  // recursion desired
+	headerBitRA = 1 << 7  // recursion available
+)
+
+var sectionNames = map[section]string{
+	sectionHeader:      "header",
+	sectionQuestions:   "Question",
+	sectionAnswers:     "Answer",
+	sectionAuthorities: "Authority",
+	sectionAdditionals: "Additional",
+}
+
+// header is the wire format for a DNS message header.
+type header struct {
+	id          uint16
+	bits        uint16
+	questions   uint16
+	answers     uint16
+	authorities uint16
+	additionals uint16
+}
+
+func (h *header) count(sec section) uint16 {
+	switch sec {
+	case sectionQuestions:
+		return h.questions
+	case sectionAnswers:
+		return h.answers
+	case sectionAuthorities:
+		return h.authorities
+	case sectionAdditionals:
+		return h.additionals
+	}
+	return 0
+}
+
+// pack appends the wire format of the header to msg.
+func (h *header) pack(msg []byte) []byte {
+	msg = packUint16(msg, h.id)
+	msg = packUint16(msg, h.bits)
+	msg = packUint16(msg, h.questions)
+	msg = packUint16(msg, h.answers)
+	msg = packUint16(msg, h.authorities)
+	return packUint16(msg, h.additionals)
+}
+
+func (h *header) unpack(msg []byte, off int) (int, error) {
+	newOff := off
+	var err error
+	if h.id, newOff, err = unpackUint16(msg, newOff); err != nil {
+		return off, &nestedError{"id", err}
+	}
+	if h.bits, newOff, err = unpackUint16(msg, newOff); err != nil {
+		return off, &nestedError{"bits", err}
+	}
+	if h.questions, newOff, err = unpackUint16(msg, newOff); err != nil {
+		return off, &nestedError{"questions", err}
+	}
+	if h.answers, newOff, err = unpackUint16(msg, newOff); err != nil {
+		return off, &nestedError{"answers", err}
+	}
+	if h.authorities, newOff, err = unpackUint16(msg, newOff); err != nil {
+		return off, &nestedError{"authorities", err}
+	}
+	if h.additionals, newOff, err = unpackUint16(msg, newOff); err != nil {
+		return off, &nestedError{"additionals", err}
+	}
+	return newOff, nil
+}
+
+func (h *header) header() Header {
+	return Header{
+		ID:                 h.id,
+		Response:           (h.bits & headerBitQR) != 0,
+		OpCode:             OpCode(h.bits>>11) & 0xF,
+		Authoritative:      (h.bits & headerBitAA) != 0,
+		Truncated:          (h.bits & headerBitTC) != 0,
+		RecursionDesired:   (h.bits & headerBitRD) != 0,
+		RecursionAvailable: (h.bits & headerBitRA) != 0,
+		RCode:              RCode(h.bits & 0xF),
+	}
+}
+
+// A Resource is a DNS resource record.
+type Resource struct {
+	Header ResourceHeader
+	Body   ResourceBody
+}
+
+// A ResourceBody is a DNS resource record minus the header.
+type ResourceBody interface {
+	// pack packs a Resource except for its header.
+	pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error)
+
+	// realType returns the actual type of the Resource. This is used to
+	// fill in the header Type field.
+	realType() Type
+}
+
+// pack appends the wire format of the Resource to msg.
+func (r *Resource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	if r.Body == nil {
+		return msg, errNilResouceBody
+	}
+	oldMsg := msg
+	r.Header.Type = r.Body.realType()
+	msg, length, err := r.Header.pack(msg, compression, compressionOff)
+	if err != nil {
+		return msg, &nestedError{"ResourceHeader", err}
+	}
+	preLen := len(msg)
+	msg, err = r.Body.pack(msg, compression, compressionOff)
+	if err != nil {
+		return msg, &nestedError{"content", err}
+	}
+	if err := r.Header.fixLen(msg, length, preLen); err != nil {
+		return oldMsg, err
+	}
+	return msg, nil
+}
+
+// A Parser allows incrementally parsing a DNS message.
+//
+// When parsing is started, the Header is parsed. Next, each Question can be
+// either parsed or skipped. Alternatively, all Questions can be skipped at
+// once. When all Questions have been parsed, attempting to parse Questions
+// will return (nil, nil) and attempting to skip Questions will return
+// (true, nil). After all Questions have been either parsed or skipped, all
+// Answers, Authorities and Additionals can be either parsed or skipped in the
+// same way, and each type of Resource must be fully parsed or skipped before
+// proceeding to the next type of Resource.
+//
+// Note that there is no requirement to fully skip or parse the message.
+type Parser struct {
+	msg    []byte
+	header header
+
+	section        section
+	off            int
+	index          int
+	resHeaderValid bool
+	resHeader      ResourceHeader
+}
+
+// Start parses the header and enables the parsing of Questions.
+func (p *Parser) Start(msg []byte) (Header, error) {
+	if p.msg != nil {
+		*p = Parser{}
+	}
+	p.msg = msg
+	var err error
+	if p.off, err = p.header.unpack(msg, 0); err != nil {
+		return Header{}, &nestedError{"unpacking header", err}
+	}
+	p.section = sectionQuestions
+	return p.header.header(), nil
+}
+
+func (p *Parser) checkAdvance(sec section) error {
+	if p.section < sec {
+		return ErrNotStarted
+	}
+	if p.section > sec {
+		return ErrSectionDone
+	}
+	p.resHeaderValid = false
+	if p.index == int(p.header.count(sec)) {
+		p.index = 0
+		p.section++
+		return ErrSectionDone
+	}
+	return nil
+}
+
+func (p *Parser) resource(sec section) (Resource, error) {
+	var r Resource
+	var err error
+	r.Header, err = p.resourceHeader(sec)
+	if err != nil {
+		return r, err
+	}
+	p.resHeaderValid = false
+	r.Body, p.off, err = unpackResourceBody(p.msg, p.off, r.Header)
+	if err != nil {
+		return Resource{}, &nestedError{"unpacking " + sectionNames[sec], err}
+	}
+	p.index++
+	return r, nil
+}
+
+func (p *Parser) resourceHeader(sec section) (ResourceHeader, error) {
+	if p.resHeaderValid {
+		return p.resHeader, nil
+	}
+	if err := p.checkAdvance(sec); err != nil {
+		return ResourceHeader{}, err
+	}
+	var hdr ResourceHeader
+	off, err := hdr.unpack(p.msg, p.off)
+	if err != nil {
+		return ResourceHeader{}, err
+	}
+	p.resHeaderValid = true
+	p.resHeader = hdr
+	p.off = off
+	return hdr, nil
+}
+
+func (p *Parser) skipResource(sec section) error {
+	if p.resHeaderValid {
+		newOff := p.off + int(p.resHeader.Length)
+		if newOff > len(p.msg) {
+			return errResourceLen
+		}
+		p.off = newOff
+		p.resHeaderValid = false
+		p.index++
+		return nil
+	}
+	if err := p.checkAdvance(sec); err != nil {
+		return err
+	}
+	var err error
+	p.off, err = skipResource(p.msg, p.off)
+	if err != nil {
+		return &nestedError{"skipping: " + sectionNames[sec], err}
+	}
+	p.index++
+	return nil
+}
+
+// Question parses a single Question.
+func (p *Parser) Question() (Question, error) {
+	if err := p.checkAdvance(sectionQuestions); err != nil {
+		return Question{}, err
+	}
+	var name Name
+	off, err := name.unpack(p.msg, p.off)
+	if err != nil {
+		return Question{}, &nestedError{"unpacking Question.Name", err}
+	}
+	typ, off, err := unpackType(p.msg, off)
+	if err != nil {
+		return Question{}, &nestedError{"unpacking Question.Type", err}
+	}
+	class, off, err := unpackClass(p.msg, off)
+	if err != nil {
+		return Question{}, &nestedError{"unpacking Question.Class", err}
+	}
+	p.off = off
+	p.index++
+	return Question{name, typ, class}, nil
+}
+
+// AllQuestions parses all Questions.
+func (p *Parser) AllQuestions() ([]Question, error) {
+	// Multiple questions are valid according to the spec,
+	// but servers don't actually support them. There will
+	// be at most one question here.
+	//
+	// Do not pre-allocate based on info in p.header, since
+	// the data is untrusted.
+	qs := []Question{}
+	for {
+		q, err := p.Question()
+		if err == ErrSectionDone {
+			return qs, nil
+		}
+		if err != nil {
+			return nil, err
+		}
+		qs = append(qs, q)
+	}
+}
+
+// SkipQuestion skips a single Question.
+func (p *Parser) SkipQuestion() error {
+	if err := p.checkAdvance(sectionQuestions); err != nil {
+		return err
+	}
+	off, err := skipName(p.msg, p.off)
+	if err != nil {
+		return &nestedError{"skipping Question Name", err}
+	}
+	if off, err = skipType(p.msg, off); err != nil {
+		return &nestedError{"skipping Question Type", err}
+	}
+	if off, err = skipClass(p.msg, off); err != nil {
+		return &nestedError{"skipping Question Class", err}
+	}
+	p.off = off
+	p.index++
+	return nil
+}
+
+// SkipAllQuestions skips all Questions.
+func (p *Parser) SkipAllQuestions() error {
+	for {
+		if err := p.SkipQuestion(); err == ErrSectionDone {
+			return nil
+		} else if err != nil {
+			return err
+		}
+	}
+}
+
+// AnswerHeader parses a single Answer ResourceHeader.
+func (p *Parser) AnswerHeader() (ResourceHeader, error) {
+	return p.resourceHeader(sectionAnswers)
+}
+
+// Answer parses a single Answer Resource.
+func (p *Parser) Answer() (Resource, error) {
+	return p.resource(sectionAnswers)
+}
+
+// AllAnswers parses all Answer Resources.
+func (p *Parser) AllAnswers() ([]Resource, error) {
+	// The most common query is for A/AAAA, which usually returns
+	// a handful of IPs.
+	//
+	// Pre-allocate up to a certain limit, since p.header is
+	// untrusted data.
+	n := int(p.header.answers)
+	if n > 20 {
+		n = 20
+	}
+	as := make([]Resource, 0, n)
+	for {
+		a, err := p.Answer()
+		if err == ErrSectionDone {
+			return as, nil
+		}
+		if err != nil {
+			return nil, err
+		}
+		as = append(as, a)
+	}
+}
+
+// SkipAnswer skips a single Answer Resource.
+func (p *Parser) SkipAnswer() error {
+	return p.skipResource(sectionAnswers)
+}
+
+// SkipAllAnswers skips all Answer Resources.
+func (p *Parser) SkipAllAnswers() error {
+	for {
+		if err := p.SkipAnswer(); err == ErrSectionDone {
+			return nil
+		} else if err != nil {
+			return err
+		}
+	}
+}
+
+// AuthorityHeader parses a single Authority ResourceHeader.
+func (p *Parser) AuthorityHeader() (ResourceHeader, error) {
+	return p.resourceHeader(sectionAuthorities)
+}
+
+// Authority parses a single Authority Resource.
+func (p *Parser) Authority() (Resource, error) {
+	return p.resource(sectionAuthorities)
+}
+
+// AllAuthorities parses all Authority Resources.
+func (p *Parser) AllAuthorities() ([]Resource, error) {
+	// Authorities contains SOA in case of NXDOMAIN and friends,
+	// otherwise it is empty.
+	//
+	// Pre-allocate up to a certain limit, since p.header is
+	// untrusted data.
+	n := int(p.header.authorities)
+	if n > 10 {
+		n = 10
+	}
+	as := make([]Resource, 0, n)
+	for {
+		a, err := p.Authority()
+		if err == ErrSectionDone {
+			return as, nil
+		}
+		if err != nil {
+			return nil, err
+		}
+		as = append(as, a)
+	}
+}
+
+// SkipAuthority skips a single Authority Resource.
+func (p *Parser) SkipAuthority() error {
+	return p.skipResource(sectionAuthorities)
+}
+
+// SkipAllAuthorities skips all Authority Resources.
+func (p *Parser) SkipAllAuthorities() error {
+	for {
+		if err := p.SkipAuthority(); err == ErrSectionDone {
+			return nil
+		} else if err != nil {
+			return err
+		}
+	}
+}
+
+// AdditionalHeader parses a single Additional ResourceHeader.
+func (p *Parser) AdditionalHeader() (ResourceHeader, error) {
+	return p.resourceHeader(sectionAdditionals)
+}
+
+// Additional parses a single Additional Resource.
+func (p *Parser) Additional() (Resource, error) {
+	return p.resource(sectionAdditionals)
+}
+
+// AllAdditionals parses all Additional Resources.
+func (p *Parser) AllAdditionals() ([]Resource, error) {
+	// Additionals usually contain OPT, and sometimes A/AAAA
+	// glue records.
+	//
+	// Pre-allocate up to a certain limit, since p.header is
+	// untrusted data.
+	n := int(p.header.additionals)
+	if n > 10 {
+		n = 10
+	}
+	as := make([]Resource, 0, n)
+	for {
+		a, err := p.Additional()
+		if err == ErrSectionDone {
+			return as, nil
+		}
+		if err != nil {
+			return nil, err
+		}
+		as = append(as, a)
+	}
+}
+
+// SkipAdditional skips a single Additional Resource.
+func (p *Parser) SkipAdditional() error {
+	return p.skipResource(sectionAdditionals)
+}
+
+// SkipAllAdditionals skips all Additional Resources.
+func (p *Parser) SkipAllAdditionals() error {
+	for {
+		if err := p.SkipAdditional(); err == ErrSectionDone {
+			return nil
+		} else if err != nil {
+			return err
+		}
+	}
+}
+
+// CNAMEResource parses a single CNAMEResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) CNAMEResource() (CNAMEResource, error) {
+	if !p.resHeaderValid || p.resHeader.Type != TypeCNAME {
+		return CNAMEResource{}, ErrNotStarted
+	}
+	r, err := unpackCNAMEResource(p.msg, p.off)
+	if err != nil {
+		return CNAMEResource{}, err
+	}
+	p.off += int(p.resHeader.Length)
+	p.resHeaderValid = false
+	p.index++
+	return r, nil
+}
+
+// MXResource parses a single MXResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) MXResource() (MXResource, error) {
+	if !p.resHeaderValid || p.resHeader.Type != TypeMX {
+		return MXResource{}, ErrNotStarted
+	}
+	r, err := unpackMXResource(p.msg, p.off)
+	if err != nil {
+		return MXResource{}, err
+	}
+	p.off += int(p.resHeader.Length)
+	p.resHeaderValid = false
+	p.index++
+	return r, nil
+}
+
+// NSResource parses a single NSResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) NSResource() (NSResource, error) {
+	if !p.resHeaderValid || p.resHeader.Type != TypeNS {
+		return NSResource{}, ErrNotStarted
+	}
+	r, err := unpackNSResource(p.msg, p.off)
+	if err != nil {
+		return NSResource{}, err
+	}
+	p.off += int(p.resHeader.Length)
+	p.resHeaderValid = false
+	p.index++
+	return r, nil
+}
+
+// PTRResource parses a single PTRResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) PTRResource() (PTRResource, error) {
+	if !p.resHeaderValid || p.resHeader.Type != TypePTR {
+		return PTRResource{}, ErrNotStarted
+	}
+	r, err := unpackPTRResource(p.msg, p.off)
+	if err != nil {
+		return PTRResource{}, err
+	}
+	p.off += int(p.resHeader.Length)
+	p.resHeaderValid = false
+	p.index++
+	return r, nil
+}
+
+// SOAResource parses a single SOAResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) SOAResource() (SOAResource, error) {
+	if !p.resHeaderValid || p.resHeader.Type != TypeSOA {
+		return SOAResource{}, ErrNotStarted
+	}
+	r, err := unpackSOAResource(p.msg, p.off)
+	if err != nil {
+		return SOAResource{}, err
+	}
+	p.off += int(p.resHeader.Length)
+	p.resHeaderValid = false
+	p.index++
+	return r, nil
+}
+
+// TXTResource parses a single TXTResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) TXTResource() (TXTResource, error) {
+	if !p.resHeaderValid || p.resHeader.Type != TypeTXT {
+		return TXTResource{}, ErrNotStarted
+	}
+	r, err := unpackTXTResource(p.msg, p.off, p.resHeader.Length)
+	if err != nil {
+		return TXTResource{}, err
+	}
+	p.off += int(p.resHeader.Length)
+	p.resHeaderValid = false
+	p.index++
+	return r, nil
+}
+
+// SRVResource parses a single SRVResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) SRVResource() (SRVResource, error) {
+	if !p.resHeaderValid || p.resHeader.Type != TypeSRV {
+		return SRVResource{}, ErrNotStarted
+	}
+	r, err := unpackSRVResource(p.msg, p.off)
+	if err != nil {
+		return SRVResource{}, err
+	}
+	p.off += int(p.resHeader.Length)
+	p.resHeaderValid = false
+	p.index++
+	return r, nil
+}
+
+// AResource parses a single AResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) AResource() (AResource, error) {
+	if !p.resHeaderValid || p.resHeader.Type != TypeA {
+		return AResource{}, ErrNotStarted
+	}
+	r, err := unpackAResource(p.msg, p.off)
+	if err != nil {
+		return AResource{}, err
+	}
+	p.off += int(p.resHeader.Length)
+	p.resHeaderValid = false
+	p.index++
+	return r, nil
+}
+
+// AAAAResource parses a single AAAAResource.
+//
+// One of the XXXHeader methods must have been called before calling this
+// method.
+func (p *Parser) AAAAResource() (AAAAResource, error) {
+	if !p.resHeaderValid || p.resHeader.Type != TypeAAAA {
+		return AAAAResource{}, ErrNotStarted
+	}
+	r, err := unpackAAAAResource(p.msg, p.off)
+	if err != nil {
+		return AAAAResource{}, 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
+	var err error
+	if m.Header, err = p.Start(msg); err != nil {
+		return err
+	}
+	if m.Questions, err = p.AllQuestions(); err != nil {
+		return err
+	}
+	if m.Answers, err = p.AllAnswers(); err != nil {
+		return err
+	}
+	if m.Authorities, err = p.AllAuthorities(); err != nil {
+		return err
+	}
+	if m.Additionals, err = p.AllAdditionals(); err != nil {
+		return err
+	}
+	return nil
+}
+
+// Pack packs a full Message.
+func (m *Message) Pack() ([]byte, error) {
+	return m.AppendPack(make([]byte, 0, packStartingCap))
+}
+
+// AppendPack is like Pack but appends the full Message to b and returns the
+// extended buffer.
+func (m *Message) AppendPack(b []byte) ([]byte, error) {
+	// Validate the lengths. It is very unlikely that anyone will try to
+	// pack more than 65535 of any particular type, but it is possible and
+	// we should fail gracefully.
+	if len(m.Questions) > int(^uint16(0)) {
+		return nil, errTooManyQuestions
+	}
+	if len(m.Answers) > int(^uint16(0)) {
+		return nil, errTooManyAnswers
+	}
+	if len(m.Authorities) > int(^uint16(0)) {
+		return nil, errTooManyAuthorities
+	}
+	if len(m.Additionals) > int(^uint16(0)) {
+		return nil, errTooManyAdditionals
+	}
+
+	var h header
+	h.id, h.bits = m.Header.pack()
+
+	h.questions = uint16(len(m.Questions))
+	h.answers = uint16(len(m.Answers))
+	h.authorities = uint16(len(m.Authorities))
+	h.additionals = uint16(len(m.Additionals))
+
+	compressionOff := len(b)
+	msg := h.pack(b)
+
+	// RFC 1035 allows (but does not require) compression for packing. RFC
+	// 1035 requires unpacking implementations to support compression, so
+	// unconditionally enabling it is fine.
+	//
+	// DNS lookups are typically done over UDP, and RFC 1035 states that UDP
+	// DNS messages can be a maximum of 512 bytes long. Without compression,
+	// many DNS response messages are over this limit, so enabling
+	// compression will help ensure compliance.
+	compression := map[string]int{}
+
+	for i := range m.Questions {
+		var err error
+		if msg, err = m.Questions[i].pack(msg, compression, compressionOff); err != nil {
+			return nil, &nestedError{"packing Question", err}
+		}
+	}
+	for i := range m.Answers {
+		var err error
+		if msg, err = m.Answers[i].pack(msg, compression, compressionOff); err != nil {
+			return nil, &nestedError{"packing Answer", err}
+		}
+	}
+	for i := range m.Authorities {
+		var err error
+		if msg, err = m.Authorities[i].pack(msg, compression, compressionOff); err != nil {
+			return nil, &nestedError{"packing Authority", err}
+		}
+	}
+	for i := range m.Additionals {
+		var err error
+		if msg, err = m.Additionals[i].pack(msg, compression, compressionOff); err != nil {
+			return nil, &nestedError{"packing Additional", err}
+		}
+	}
+
+	return msg, nil
+}
+
+// A Builder allows incrementally packing a DNS message.
+//
+// Example usage:
+//	buf := make([]byte, 2, 514)
+//	b := NewBuilder(buf, Header{...})
+//	b.EnableCompression()
+//	// Optionally start a section and add things to that section.
+//	// Repeat adding sections as necessary.
+//	buf, err := b.Finish()
+//	// If err is nil, buf[2:] will contain the built bytes.
+type Builder struct {
+	// msg is the storage for the message being built.
+	msg []byte
+
+	// section keeps track of the current section being built.
+	section section
+
+	// header keeps track of what should go in the header when Finish is
+	// called.
+	header header
+
+	// start is the starting index of the bytes allocated in msg for header.
+	start int
+
+	// compression is a mapping from name suffixes to their starting index
+	// in msg.
+	compression map[string]int
+}
+
+// NewBuilder creates a new builder with compression disabled.
+//
+// Note: Most users will want to immediately enable compression with the
+// EnableCompression method. See that method's comment for why you may or may
+// not want to enable compression.
+//
+// The DNS message is appended to the provided initial buffer buf (which may be
+// nil) as it is built. The final message is returned by the (*Builder).Finish
+// method, which may return the same underlying array if there was sufficient
+// capacity in the slice.
+func NewBuilder(buf []byte, h Header) Builder {
+	if buf == nil {
+		buf = make([]byte, 0, packStartingCap)
+	}
+	b := Builder{msg: buf, start: len(buf)}
+	b.header.id, b.header.bits = h.pack()
+	var hb [headerLen]byte
+	b.msg = append(b.msg, hb[:]...)
+	b.section = sectionHeader
+	return b
+}
+
+// EnableCompression enables compression in the Builder.
+//
+// Leaving compression disabled avoids compression related allocations, but can
+// result in larger message sizes. Be careful with this mode as it can cause
+// messages to exceed the UDP size limit.
+//
+// According to RFC 1035, section 4.1.4, the use of compression is optional, but
+// all implementations must accept both compressed and uncompressed DNS
+// messages.
+//
+// Compression should be enabled before any sections are added for best results.
+func (b *Builder) EnableCompression() {
+	b.compression = map[string]int{}
+}
+
+func (b *Builder) startCheck(s section) error {
+	if b.section <= sectionNotStarted {
+		return ErrNotStarted
+	}
+	if b.section > s {
+		return ErrSectionDone
+	}
+	return nil
+}
+
+// StartQuestions prepares the builder for packing Questions.
+func (b *Builder) StartQuestions() error {
+	if err := b.startCheck(sectionQuestions); err != nil {
+		return err
+	}
+	b.section = sectionQuestions
+	return nil
+}
+
+// StartAnswers prepares the builder for packing Answers.
+func (b *Builder) StartAnswers() error {
+	if err := b.startCheck(sectionAnswers); err != nil {
+		return err
+	}
+	b.section = sectionAnswers
+	return nil
+}
+
+// StartAuthorities prepares the builder for packing Authorities.
+func (b *Builder) StartAuthorities() error {
+	if err := b.startCheck(sectionAuthorities); err != nil {
+		return err
+	}
+	b.section = sectionAuthorities
+	return nil
+}
+
+// StartAdditionals prepares the builder for packing Additionals.
+func (b *Builder) StartAdditionals() error {
+	if err := b.startCheck(sectionAdditionals); err != nil {
+		return err
+	}
+	b.section = sectionAdditionals
+	return nil
+}
+
+func (b *Builder) incrementSectionCount() error {
+	var count *uint16
+	var err error
+	switch b.section {
+	case sectionQuestions:
+		count = &b.header.questions
+		err = errTooManyQuestions
+	case sectionAnswers:
+		count = &b.header.answers
+		err = errTooManyAnswers
+	case sectionAuthorities:
+		count = &b.header.authorities
+		err = errTooManyAuthorities
+	case sectionAdditionals:
+		count = &b.header.additionals
+		err = errTooManyAdditionals
+	}
+	if *count == ^uint16(0) {
+		return err
+	}
+	*count++
+	return nil
+}
+
+// Question adds a single Question.
+func (b *Builder) Question(q Question) error {
+	if b.section < sectionQuestions {
+		return ErrNotStarted
+	}
+	if b.section > sectionQuestions {
+		return ErrSectionDone
+	}
+	msg, err := q.pack(b.msg, b.compression, b.start)
+	if err != nil {
+		return err
+	}
+	if err := b.incrementSectionCount(); err != nil {
+		return err
+	}
+	b.msg = msg
+	return nil
+}
+
+func (b *Builder) checkResourceSection() error {
+	if b.section < sectionAnswers {
+		return ErrNotStarted
+	}
+	if b.section > sectionAdditionals {
+		return ErrSectionDone
+	}
+	return nil
+}
+
+// CNAMEResource adds a single CNAMEResource.
+func (b *Builder) CNAMEResource(h ResourceHeader, r CNAMEResource) error {
+	if err := b.checkResourceSection(); err != nil {
+		return err
+	}
+	h.Type = r.realType()
+	msg, length, 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{"CNAMEResource body", err}
+	}
+	if err := h.fixLen(msg, length, preLen); err != nil {
+		return err
+	}
+	if err := b.incrementSectionCount(); err != nil {
+		return err
+	}
+	b.msg = msg
+	return nil
+}
+
+// MXResource adds a single MXResource.
+func (b *Builder) MXResource(h ResourceHeader, r MXResource) error {
+	if err := b.checkResourceSection(); err != nil {
+		return err
+	}
+	h.Type = r.realType()
+	msg, length, 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{"MXResource body", err}
+	}
+	if err := h.fixLen(msg, length, preLen); err != nil {
+		return err
+	}
+	if err := b.incrementSectionCount(); err != nil {
+		return err
+	}
+	b.msg = msg
+	return nil
+}
+
+// NSResource adds a single NSResource.
+func (b *Builder) NSResource(h ResourceHeader, r NSResource) error {
+	if err := b.checkResourceSection(); err != nil {
+		return err
+	}
+	h.Type = r.realType()
+	msg, length, 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{"NSResource body", err}
+	}
+	if err := h.fixLen(msg, length, preLen); err != nil {
+		return err
+	}
+	if err := b.incrementSectionCount(); err != nil {
+		return err
+	}
+	b.msg = msg
+	return nil
+}
+
+// PTRResource adds a single PTRResource.
+func (b *Builder) PTRResource(h ResourceHeader, r PTRResource) error {
+	if err := b.checkResourceSection(); err != nil {
+		return err
+	}
+	h.Type = r.realType()
+	msg, length, 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{"PTRResource body", err}
+	}
+	if err := h.fixLen(msg, length, preLen); err != nil {
+		return err
+	}
+	if err := b.incrementSectionCount(); err != nil {
+		return err
+	}
+	b.msg = msg
+	return nil
+}
+
+// SOAResource adds a single SOAResource.
+func (b *Builder) SOAResource(h ResourceHeader, r SOAResource) error {
+	if err := b.checkResourceSection(); err != nil {
+		return err
+	}
+	h.Type = r.realType()
+	msg, length, 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{"SOAResource body", err}
+	}
+	if err := h.fixLen(msg, length, preLen); err != nil {
+		return err
+	}
+	if err := b.incrementSectionCount(); err != nil {
+		return err
+	}
+	b.msg = msg
+	return nil
+}
+
+// TXTResource adds a single TXTResource.
+func (b *Builder) TXTResource(h ResourceHeader, r TXTResource) error {
+	if err := b.checkResourceSection(); err != nil {
+		return err
+	}
+	h.Type = r.realType()
+	msg, length, 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{"TXTResource body", err}
+	}
+	if err := h.fixLen(msg, length, preLen); err != nil {
+		return err
+	}
+	if err := b.incrementSectionCount(); err != nil {
+		return err
+	}
+	b.msg = msg
+	return nil
+}
+
+// SRVResource adds a single SRVResource.
+func (b *Builder) SRVResource(h ResourceHeader, r SRVResource) error {
+	if err := b.checkResourceSection(); err != nil {
+		return err
+	}
+	h.Type = r.realType()
+	msg, length, 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{"SRVResource body", err}
+	}
+	if err := h.fixLen(msg, length, preLen); err != nil {
+		return err
+	}
+	if err := b.incrementSectionCount(); err != nil {
+		return err
+	}
+	b.msg = msg
+	return nil
+}
+
+// AResource adds a single AResource.
+func (b *Builder) AResource(h ResourceHeader, r AResource) error {
+	if err := b.checkResourceSection(); err != nil {
+		return err
+	}
+	h.Type = r.realType()
+	msg, length, 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{"AResource body", err}
+	}
+	if err := h.fixLen(msg, length, preLen); err != nil {
+		return err
+	}
+	if err := b.incrementSectionCount(); err != nil {
+		return err
+	}
+	b.msg = msg
+	return nil
+}
+
+// AAAAResource adds a single AAAAResource.
+func (b *Builder) AAAAResource(h ResourceHeader, r AAAAResource) error {
+	if err := b.checkResourceSection(); err != nil {
+		return err
+	}
+	h.Type = r.realType()
+	msg, length, 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{"AAAAResource body", err}
+	}
+	if err := h.fixLen(msg, length, 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 {
+		return nil, ErrNotStarted
+	}
+	b.section = sectionDone
+	// Space for the header was allocated in NewBuilder.
+	b.header.pack(b.msg[b.start:b.start])
+	return b.msg, nil
+}
+
+// A ResourceHeader is the header of a DNS resource record. There are
+// many types of DNS resource records, but they all share the same header.
+type ResourceHeader struct {
+	// Name is the domain name for which this resource record pertains.
+	Name Name
+
+	// Type is the type of DNS resource record.
+	//
+	// This field will be set automatically during packing.
+	Type Type
+
+	// Class is the class of network to which this DNS resource record
+	// pertains.
+	Class Class
+
+	// TTL is the length of time (measured in seconds) which this resource
+	// record is valid for (time to live). All Resources in a set should
+	// have the same TTL (RFC 2181 Section 5.2).
+	TTL uint32
+
+	// Length is the length of data in the resource record after the header.
+	//
+	// This field will be set automatically during packing.
+	Length uint16
+}
+
+// pack appends the wire format of the ResourceHeader to oldMsg.
+//
+// The bytes where length was packed are returned as a slice so they can be
+// updated after the rest of the Resource has been packed.
+func (h *ResourceHeader) pack(oldMsg []byte, compression map[string]int, compressionOff int) (msg []byte, length []byte, err error) {
+	msg = oldMsg
+	if msg, err = h.Name.pack(msg, compression, compressionOff); err != nil {
+		return oldMsg, nil, &nestedError{"Name", err}
+	}
+	msg = packType(msg, h.Type)
+	msg = packClass(msg, h.Class)
+	msg = packUint32(msg, h.TTL)
+	lenBegin := len(msg)
+	msg = packUint16(msg, h.Length)
+	return msg, msg[lenBegin : lenBegin+uint16Len], nil
+}
+
+func (h *ResourceHeader) unpack(msg []byte, off int) (int, error) {
+	newOff := off
+	var err error
+	if newOff, err = h.Name.unpack(msg, newOff); err != nil {
+		return off, &nestedError{"Name", err}
+	}
+	if h.Type, newOff, err = unpackType(msg, newOff); err != nil {
+		return off, &nestedError{"Type", err}
+	}
+	if h.Class, newOff, err = unpackClass(msg, newOff); err != nil {
+		return off, &nestedError{"Class", err}
+	}
+	if h.TTL, newOff, err = unpackUint32(msg, newOff); err != nil {
+		return off, &nestedError{"TTL", err}
+	}
+	if h.Length, newOff, err = unpackUint16(msg, newOff); err != nil {
+		return off, &nestedError{"Length", err}
+	}
+	return newOff, nil
+}
+
+func (h *ResourceHeader) fixLen(msg []byte, length []byte, preLen int) error {
+	conLen := len(msg) - preLen
+	if conLen > int(^uint16(0)) {
+		return errResTooLong
+	}
+
+	// Fill in the length now that we know how long the content is.
+	packUint16(length[:0], uint16(conLen))
+	h.Length = uint16(conLen)
+
+	return nil
+}
+
+func skipResource(msg []byte, off int) (int, error) {
+	newOff, err := skipName(msg, off)
+	if err != nil {
+		return off, &nestedError{"Name", err}
+	}
+	if newOff, err = skipType(msg, newOff); err != nil {
+		return off, &nestedError{"Type", err}
+	}
+	if newOff, err = skipClass(msg, newOff); err != nil {
+		return off, &nestedError{"Class", err}
+	}
+	if newOff, err = skipUint32(msg, newOff); err != nil {
+		return off, &nestedError{"TTL", err}
+	}
+	length, newOff, err := unpackUint16(msg, newOff)
+	if err != nil {
+		return off, &nestedError{"Length", err}
+	}
+	if newOff += int(length); newOff > len(msg) {
+		return off, errResourceLen
+	}
+	return newOff, nil
+}
+
+// packUint16 appends the wire format of field to msg.
+func packUint16(msg []byte, field uint16) []byte {
+	return append(msg, byte(field>>8), byte(field))
+}
+
+func unpackUint16(msg []byte, off int) (uint16, int, error) {
+	if off+uint16Len > len(msg) {
+		return 0, off, errBaseLen
+	}
+	return uint16(msg[off])<<8 | uint16(msg[off+1]), off + uint16Len, nil
+}
+
+func skipUint16(msg []byte, off int) (int, error) {
+	if off+uint16Len > len(msg) {
+		return off, errBaseLen
+	}
+	return off + uint16Len, nil
+}
+
+// packType appends the wire format of field to msg.
+func packType(msg []byte, field Type) []byte {
+	return packUint16(msg, uint16(field))
+}
+
+func unpackType(msg []byte, off int) (Type, int, error) {
+	t, o, err := unpackUint16(msg, off)
+	return Type(t), o, err
+}
+
+func skipType(msg []byte, off int) (int, error) {
+	return skipUint16(msg, off)
+}
+
+// packClass appends the wire format of field to msg.
+func packClass(msg []byte, field Class) []byte {
+	return packUint16(msg, uint16(field))
+}
+
+func unpackClass(msg []byte, off int) (Class, int, error) {
+	c, o, err := unpackUint16(msg, off)
+	return Class(c), o, err
+}
+
+func skipClass(msg []byte, off int) (int, error) {
+	return skipUint16(msg, off)
+}
+
+// packUint32 appends the wire format of field to msg.
+func packUint32(msg []byte, field uint32) []byte {
+	return append(
+		msg,
+		byte(field>>24),
+		byte(field>>16),
+		byte(field>>8),
+		byte(field),
+	)
+}
+
+func unpackUint32(msg []byte, off int) (uint32, int, error) {
+	if off+uint32Len > len(msg) {
+		return 0, off, errBaseLen
+	}
+	v := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])
+	return v, off + uint32Len, nil
+}
+
+func skipUint32(msg []byte, off int) (int, error) {
+	if off+uint32Len > len(msg) {
+		return off, errBaseLen
+	}
+	return off + uint32Len, nil
+}
+
+// packText appends the wire format of field to msg.
+func packText(msg []byte, field string) ([]byte, error) {
+	l := len(field)
+	if l > 255 {
+		return nil, errStringTooLong
+	}
+	msg = append(msg, byte(l))
+	msg = append(msg, field...)
+
+	return msg, nil
+}
+
+func unpackText(msg []byte, off int) (string, int, error) {
+	if off >= len(msg) {
+		return "", off, errBaseLen
+	}
+	beginOff := off + 1
+	endOff := beginOff + int(msg[off])
+	if endOff > len(msg) {
+		return "", off, errCalcLen
+	}
+	return string(msg[beginOff:endOff]), endOff, nil
+}
+
+func skipText(msg []byte, off int) (int, error) {
+	if off >= len(msg) {
+		return off, errBaseLen
+	}
+	endOff := off + 1 + int(msg[off])
+	if endOff > len(msg) {
+		return off, errCalcLen
+	}
+	return endOff, nil
+}
+
+// packBytes appends the wire format of field to msg.
+func packBytes(msg []byte, field []byte) []byte {
+	return append(msg, field...)
+}
+
+func unpackBytes(msg []byte, off int, field []byte) (int, error) {
+	newOff := off + len(field)
+	if newOff > len(msg) {
+		return off, errBaseLen
+	}
+	copy(field, msg[off:newOff])
+	return newOff, nil
+}
+
+func skipBytes(msg []byte, off int, field []byte) (int, error) {
+	newOff := off + len(field)
+	if newOff > len(msg) {
+		return off, errBaseLen
+	}
+	return newOff, nil
+}
+
+const nameLen = 255
+
+// A Name is a non-encoded domain name. It is used instead of strings to avoid
+// allocations.
+type Name struct {
+	Data   [nameLen]byte
+	Length uint8
+}
+
+// NewName creates a new Name from a string.
+func NewName(name string) (Name, error) {
+	if len([]byte(name)) > nameLen {
+		return Name{}, errCalcLen
+	}
+	n := Name{Length: uint8(len(name))}
+	copy(n.Data[:], []byte(name))
+	return n, nil
+}
+
+func (n Name) String() string {
+	return string(n.Data[:n.Length])
+}
+
+// pack appends the wire format of the Name to msg.
+//
+// Domain names are a sequence of counted strings split at the dots. They end
+// with a zero-length string. Compression can be used to reuse domain suffixes.
+//
+// The compression map will be updated with new domain suffixes. If compression
+// is nil, compression will not be used.
+func (n *Name) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	oldMsg := msg
+
+	// Add a trailing dot to canonicalize name.
+	if n.Length == 0 || n.Data[n.Length-1] != '.' {
+		return oldMsg, errNonCanonicalName
+	}
+
+	// Allow root domain.
+	if n.Data[0] == '.' && n.Length == 1 {
+		return append(msg, 0), nil
+	}
+
+	// Emit sequence of counted strings, chopping at dots.
+	for i, begin := 0, 0; i < int(n.Length); i++ {
+		// Check for the end of the segment.
+		if n.Data[i] == '.' {
+			// The two most significant bits have special meaning.
+			// It isn't allowed for segments to be long enough to
+			// need them.
+			if i-begin >= 1<<6 {
+				return oldMsg, errSegTooLong
+			}
+
+			// Segments must have a non-zero length.
+			if i-begin == 0 {
+				return oldMsg, errZeroSegLen
+			}
+
+			msg = append(msg, byte(i-begin))
+
+			for j := begin; j < i; j++ {
+				msg = append(msg, n.Data[j])
+			}
+
+			begin = i + 1
+			continue
+		}
+
+		// We can only compress domain suffixes starting with a new
+		// segment. A pointer is two bytes with the two most significant
+		// bits set to 1 to indicate that it is a pointer.
+		if (i == 0 || n.Data[i-1] == '.') && compression != nil {
+			if ptr, ok := compression[string(n.Data[i:])]; ok {
+				// Hit. Emit a pointer instead of the rest of
+				// the domain.
+				return append(msg, byte(ptr>>8|0xC0), byte(ptr)), nil
+			}
+
+			// Miss. Add the suffix to the compression table if the
+			// offset can be stored in the available 14 bytes.
+			if len(msg) <= int(^uint16(0)>>2) {
+				compression[string(n.Data[i:])] = len(msg) - compressionOff
+			}
+		}
+	}
+	return append(msg, 0), nil
+}
+
+// unpack unpacks a domain name.
+func (n *Name) unpack(msg []byte, off int) (int, error) {
+	return n.unpackCompressed(msg, off, true /* allowCompression */)
+}
+
+func (n *Name) unpackCompressed(msg []byte, off int, allowCompression bool) (int, error) {
+	// currOff is the current working offset.
+	currOff := off
+
+	// newOff is the offset where the next record will start. Pointers lead
+	// to data that belongs to other names and thus doesn't count towards to
+	// the usage of this name.
+	newOff := off
+
+	// ptr is the number of pointers followed.
+	var ptr int
+
+	// Name is a slice representation of the name data.
+	name := n.Data[:0]
+
+Loop:
+	for {
+		if currOff >= len(msg) {
+			return off, errBaseLen
+		}
+		c := int(msg[currOff])
+		currOff++
+		switch c & 0xC0 {
+		case 0x00: // String segment
+			if c == 0x00 {
+				// A zero length signals the end of the name.
+				break Loop
+			}
+			endOff := currOff + c
+			if endOff > len(msg) {
+				return off, errCalcLen
+			}
+			name = append(name, msg[currOff:endOff]...)
+			name = append(name, '.')
+			currOff = endOff
+		case 0xC0: // Pointer
+			if !allowCompression {
+				return off, errCompressedSRV
+			}
+			if currOff >= len(msg) {
+				return off, errInvalidPtr
+			}
+			c1 := msg[currOff]
+			currOff++
+			if ptr == 0 {
+				newOff = currOff
+			}
+			// Don't follow too many pointers, maybe there's a loop.
+			if ptr++; ptr > 10 {
+				return off, errTooManyPtr
+			}
+			currOff = (c^0xC0)<<8 | int(c1)
+		default:
+			// Prefixes 0x80 and 0x40 are reserved.
+			return off, errReserved
+		}
+	}
+	if len(name) == 0 {
+		name = append(name, '.')
+	}
+	if len(name) > len(n.Data) {
+		return off, errCalcLen
+	}
+	n.Length = uint8(len(name))
+	if ptr == 0 {
+		newOff = currOff
+	}
+	return newOff, nil
+}
+
+func skipName(msg []byte, off int) (int, error) {
+	// newOff is the offset where the next record will start. Pointers lead
+	// to data that belongs to other names and thus doesn't count towards to
+	// the usage of this name.
+	newOff := off
+
+Loop:
+	for {
+		if newOff >= len(msg) {
+			return off, errBaseLen
+		}
+		c := int(msg[newOff])
+		newOff++
+		switch c & 0xC0 {
+		case 0x00:
+			if c == 0x00 {
+				// A zero length signals the end of the name.
+				break Loop
+			}
+			// literal string
+			newOff += c
+			if newOff > len(msg) {
+				return off, errCalcLen
+			}
+		case 0xC0:
+			// Pointer to somewhere else in msg.
+
+			// Pointers are two bytes.
+			newOff++
+
+			// Don't follow the pointer as the data here has ended.
+			break Loop
+		default:
+			// Prefixes 0x80 and 0x40 are reserved.
+			return off, errReserved
+		}
+	}
+
+	return newOff, nil
+}
+
+// A Question is a DNS query.
+type Question struct {
+	Name  Name
+	Type  Type
+	Class Class
+}
+
+// pack appends the wire format of the Question to msg.
+func (q *Question) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	msg, err := q.Name.pack(msg, compression, compressionOff)
+	if err != nil {
+		return msg, &nestedError{"Name", err}
+	}
+	msg = packType(msg, q.Type)
+	return packClass(msg, q.Class), nil
+}
+
+func unpackResourceBody(msg []byte, off int, hdr ResourceHeader) (ResourceBody, int, error) {
+	var (
+		r    ResourceBody
+		err  error
+		name string
+	)
+	switch hdr.Type {
+	case TypeA:
+		var rb AResource
+		rb, err = unpackAResource(msg, off)
+		r = &rb
+		name = "A"
+	case TypeNS:
+		var rb NSResource
+		rb, err = unpackNSResource(msg, off)
+		r = &rb
+		name = "NS"
+	case TypeCNAME:
+		var rb CNAMEResource
+		rb, err = unpackCNAMEResource(msg, off)
+		r = &rb
+		name = "CNAME"
+	case TypeSOA:
+		var rb SOAResource
+		rb, err = unpackSOAResource(msg, off)
+		r = &rb
+		name = "SOA"
+	case TypePTR:
+		var rb PTRResource
+		rb, err = unpackPTRResource(msg, off)
+		r = &rb
+		name = "PTR"
+	case TypeMX:
+		var rb MXResource
+		rb, err = unpackMXResource(msg, off)
+		r = &rb
+		name = "MX"
+	case TypeTXT:
+		var rb TXTResource
+		rb, err = unpackTXTResource(msg, off, hdr.Length)
+		r = &rb
+		name = "TXT"
+	case TypeAAAA:
+		var rb AAAAResource
+		rb, err = unpackAAAAResource(msg, off)
+		r = &rb
+		name = "AAAA"
+	case TypeSRV:
+		var rb SRVResource
+		rb, err = unpackSRVResource(msg, off)
+		r = &rb
+		name = "SRV"
+	}
+	if err != nil {
+		return nil, off, &nestedError{name + " record", err}
+	}
+	if r == nil {
+		return nil, off, errors.New("invalid resource type: " + string(hdr.Type+'0'))
+	}
+	return r, off + int(hdr.Length), nil
+}
+
+// A CNAMEResource is a CNAME Resource record.
+type CNAMEResource struct {
+	CNAME Name
+}
+
+func (r *CNAMEResource) realType() Type {
+	return TypeCNAME
+}
+
+// pack appends the wire format of the CNAMEResource to msg.
+func (r *CNAMEResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	return r.CNAME.pack(msg, compression, compressionOff)
+}
+
+func unpackCNAMEResource(msg []byte, off int) (CNAMEResource, error) {
+	var cname Name
+	if _, err := cname.unpack(msg, off); err != nil {
+		return CNAMEResource{}, err
+	}
+	return CNAMEResource{cname}, nil
+}
+
+// An MXResource is an MX Resource record.
+type MXResource struct {
+	Pref uint16
+	MX   Name
+}
+
+func (r *MXResource) realType() Type {
+	return TypeMX
+}
+
+// pack appends the wire format of the MXResource to msg.
+func (r *MXResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	oldMsg := msg
+	msg = packUint16(msg, r.Pref)
+	msg, err := r.MX.pack(msg, compression, compressionOff)
+	if err != nil {
+		return oldMsg, &nestedError{"MXResource.MX", err}
+	}
+	return msg, nil
+}
+
+func unpackMXResource(msg []byte, off int) (MXResource, error) {
+	pref, off, err := unpackUint16(msg, off)
+	if err != nil {
+		return MXResource{}, &nestedError{"Pref", err}
+	}
+	var mx Name
+	if _, err := mx.unpack(msg, off); err != nil {
+		return MXResource{}, &nestedError{"MX", err}
+	}
+	return MXResource{pref, mx}, nil
+}
+
+// An NSResource is an NS Resource record.
+type NSResource struct {
+	NS Name
+}
+
+func (r *NSResource) realType() Type {
+	return TypeNS
+}
+
+// pack appends the wire format of the NSResource to msg.
+func (r *NSResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	return r.NS.pack(msg, compression, compressionOff)
+}
+
+func unpackNSResource(msg []byte, off int) (NSResource, error) {
+	var ns Name
+	if _, err := ns.unpack(msg, off); err != nil {
+		return NSResource{}, err
+	}
+	return NSResource{ns}, nil
+}
+
+// A PTRResource is a PTR Resource record.
+type PTRResource struct {
+	PTR Name
+}
+
+func (r *PTRResource) realType() Type {
+	return TypePTR
+}
+
+// pack appends the wire format of the PTRResource to msg.
+func (r *PTRResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	return r.PTR.pack(msg, compression, compressionOff)
+}
+
+func unpackPTRResource(msg []byte, off int) (PTRResource, error) {
+	var ptr Name
+	if _, err := ptr.unpack(msg, off); err != nil {
+		return PTRResource{}, err
+	}
+	return PTRResource{ptr}, nil
+}
+
+// An SOAResource is an SOA Resource record.
+type SOAResource struct {
+	NS      Name
+	MBox    Name
+	Serial  uint32
+	Refresh uint32
+	Retry   uint32
+	Expire  uint32
+
+	// MinTTL the is the default TTL of Resources records which did not
+	// contain a TTL value and the TTL of negative responses. (RFC 2308
+	// Section 4)
+	MinTTL uint32
+}
+
+func (r *SOAResource) realType() Type {
+	return TypeSOA
+}
+
+// pack appends the wire format of the SOAResource to msg.
+func (r *SOAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	oldMsg := msg
+	msg, err := r.NS.pack(msg, compression, compressionOff)
+	if err != nil {
+		return oldMsg, &nestedError{"SOAResource.NS", err}
+	}
+	msg, err = r.MBox.pack(msg, compression, compressionOff)
+	if err != nil {
+		return oldMsg, &nestedError{"SOAResource.MBox", err}
+	}
+	msg = packUint32(msg, r.Serial)
+	msg = packUint32(msg, r.Refresh)
+	msg = packUint32(msg, r.Retry)
+	msg = packUint32(msg, r.Expire)
+	return packUint32(msg, r.MinTTL), nil
+}
+
+func unpackSOAResource(msg []byte, off int) (SOAResource, error) {
+	var ns Name
+	off, err := ns.unpack(msg, off)
+	if err != nil {
+		return SOAResource{}, &nestedError{"NS", err}
+	}
+	var mbox Name
+	if off, err = mbox.unpack(msg, off); err != nil {
+		return SOAResource{}, &nestedError{"MBox", err}
+	}
+	serial, off, err := unpackUint32(msg, off)
+	if err != nil {
+		return SOAResource{}, &nestedError{"Serial", err}
+	}
+	refresh, off, err := unpackUint32(msg, off)
+	if err != nil {
+		return SOAResource{}, &nestedError{"Refresh", err}
+	}
+	retry, off, err := unpackUint32(msg, off)
+	if err != nil {
+		return SOAResource{}, &nestedError{"Retry", err}
+	}
+	expire, off, err := unpackUint32(msg, off)
+	if err != nil {
+		return SOAResource{}, &nestedError{"Expire", err}
+	}
+	minTTL, _, err := unpackUint32(msg, off)
+	if err != nil {
+		return SOAResource{}, &nestedError{"MinTTL", err}
+	}
+	return SOAResource{ns, mbox, serial, refresh, retry, expire, minTTL}, nil
+}
+
+// A TXTResource is a TXT Resource record.
+type TXTResource struct {
+	TXT []string
+}
+
+func (r *TXTResource) realType() Type {
+	return TypeTXT
+}
+
+// pack appends the wire format of the TXTResource to msg.
+func (r *TXTResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	oldMsg := msg
+	for _, s := range r.TXT {
+		var err error
+		msg, err = packText(msg, s)
+		if err != nil {
+			return oldMsg, err
+		}
+	}
+	return msg, nil
+}
+
+func unpackTXTResource(msg []byte, off int, length uint16) (TXTResource, error) {
+	txts := make([]string, 0, 1)
+	for n := uint16(0); n < length; {
+		var t string
+		var err error
+		if t, off, err = unpackText(msg, off); err != nil {
+			return TXTResource{}, &nestedError{"text", err}
+		}
+		// Check if we got too many bytes.
+		if length-n < uint16(len(t))+1 {
+			return TXTResource{}, errCalcLen
+		}
+		n += uint16(len(t)) + 1
+		txts = append(txts, t)
+	}
+	return TXTResource{txts}, nil
+}
+
+// An SRVResource is an SRV Resource record.
+type SRVResource struct {
+	Priority uint16
+	Weight   uint16
+	Port     uint16
+	Target   Name // Not compressed as per RFC 2782.
+}
+
+func (r *SRVResource) realType() Type {
+	return TypeSRV
+}
+
+// pack appends the wire format of the SRVResource to msg.
+func (r *SRVResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	oldMsg := msg
+	msg = packUint16(msg, r.Priority)
+	msg = packUint16(msg, r.Weight)
+	msg = packUint16(msg, r.Port)
+	msg, err := r.Target.pack(msg, nil, compressionOff)
+	if err != nil {
+		return oldMsg, &nestedError{"SRVResource.Target", err}
+	}
+	return msg, nil
+}
+
+func unpackSRVResource(msg []byte, off int) (SRVResource, error) {
+	priority, off, err := unpackUint16(msg, off)
+	if err != nil {
+		return SRVResource{}, &nestedError{"Priority", err}
+	}
+	weight, off, err := unpackUint16(msg, off)
+	if err != nil {
+		return SRVResource{}, &nestedError{"Weight", err}
+	}
+	port, off, err := unpackUint16(msg, off)
+	if err != nil {
+		return SRVResource{}, &nestedError{"Port", err}
+	}
+	var target Name
+	if _, err := target.unpackCompressed(msg, off, false /* allowCompression */); err != nil {
+		return SRVResource{}, &nestedError{"Target", err}
+	}
+	return SRVResource{priority, weight, port, target}, nil
+}
+
+// An AResource is an A Resource record.
+type AResource struct {
+	A [4]byte
+}
+
+func (r *AResource) realType() Type {
+	return TypeA
+}
+
+// pack appends the wire format of the AResource to msg.
+func (r *AResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	return packBytes(msg, r.A[:]), nil
+}
+
+func unpackAResource(msg []byte, off int) (AResource, error) {
+	var a [4]byte
+	if _, err := unpackBytes(msg, off, a[:]); err != nil {
+		return AResource{}, err
+	}
+	return AResource{a}, nil
+}
+
+// An AAAAResource is an AAAA Resource record.
+type AAAAResource struct {
+	AAAA [16]byte
+}
+
+func (r *AAAAResource) realType() Type {
+	return TypeAAAA
+}
+
+// pack appends the wire format of the AAAAResource to msg.
+func (r *AAAAResource) pack(msg []byte, compression map[string]int, compressionOff int) ([]byte, error) {
+	return packBytes(msg, r.AAAA[:]), nil
+}
+
+func unpackAAAAResource(msg []byte, off int) (AAAAResource, error) {
+	var aaaa [16]byte
+	if _, err := unpackBytes(msg, off, aaaa[:]); err != nil {
+		return AAAAResource{}, err
+	}
+	return AAAAResource{aaaa}, nil
+}
diff --git a/libgo/go/golang_org/x/net/dns/dnsmessage/message_test.go b/libgo/go/golang_org/x/net/dns/dnsmessage/message_test.go
new file mode 100644
index 00000000000..052897f3cf5
--- /dev/null
+++ b/libgo/go/golang_org/x/net/dns/dnsmessage/message_test.go
@@ -0,0 +1,1137 @@
+// 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 dnsmessage
+
+import (
+	"bytes"
+	"fmt"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func mustNewName(name string) Name {
+	n, err := NewName(name)
+	if err != nil {
+		panic(err)
+	}
+	return n
+}
+
+func (m *Message) String() string {
+	s := fmt.Sprintf("Message: %#v\n", &m.Header)
+	if len(m.Questions) > 0 {
+		s += "-- Questions\n"
+		for _, q := range m.Questions {
+			s += fmt.Sprintf("%#v\n", q)
+		}
+	}
+	if len(m.Answers) > 0 {
+		s += "-- Answers\n"
+		for _, a := range m.Answers {
+			s += fmt.Sprintf("%#v\n", a)
+		}
+	}
+	if len(m.Authorities) > 0 {
+		s += "-- Authorities\n"
+		for _, ns := range m.Authorities {
+			s += fmt.Sprintf("%#v\n", ns)
+		}
+	}
+	if len(m.Additionals) > 0 {
+		s += "-- Additionals\n"
+		for _, e := range m.Additionals {
+			s += fmt.Sprintf("%#v\n", e)
+		}
+	}
+	return s
+}
+
+func TestNameString(t *testing.T) {
+	want := "foo"
+	name := mustNewName(want)
+	if got := fmt.Sprint(name); got != want {
+		t.Errorf("got fmt.Sprint(%#v) = %s, want = %s", name, got, want)
+	}
+}
+
+func TestQuestionPackUnpack(t *testing.T) {
+	want := Question{
+		Name:  mustNewName("."),
+		Type:  TypeA,
+		Class: ClassINET,
+	}
+	buf, err := want.pack(make([]byte, 1, 50), map[string]int{}, 1)
+	if err != nil {
+		t.Fatal("Packing failed:", err)
+	}
+	var p Parser
+	p.msg = buf
+	p.header.questions = 1
+	p.section = sectionQuestions
+	p.off = 1
+	got, err := p.Question()
+	if err != nil {
+		t.Fatalf("Unpacking failed: %v\n%s", err, string(buf[1:]))
+	}
+	if p.off != len(buf) {
+		t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", p.off, len(buf))
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Got = %+v, want = %+v", got, want)
+	}
+}
+
+func TestName(t *testing.T) {
+	tests := []string{
+		"",
+		".",
+		"google..com",
+		"google.com",
+		"google..com.",
+		"google.com.",
+		".google.com.",
+		"www..google.com.",
+		"www.google.com.",
+	}
+
+	for _, test := range tests {
+		n, err := NewName(test)
+		if err != nil {
+			t.Errorf("Creating name for %q: %v", test, err)
+			continue
+		}
+		if ns := n.String(); ns != test {
+			t.Errorf("Got %#v.String() = %q, want = %q", n, ns, test)
+			continue
+		}
+	}
+}
+
+func TestNamePackUnpack(t *testing.T) {
+	tests := []struct {
+		in   string
+		want string
+		err  error
+	}{
+		{"", "", errNonCanonicalName},
+		{".", ".", nil},
+		{"google..com", "", errNonCanonicalName},
+		{"google.com", "", errNonCanonicalName},
+		{"google..com.", "", errZeroSegLen},
+		{"google.com.", "google.com.", nil},
+		{".google.com.", "", errZeroSegLen},
+		{"www..google.com.", "", errZeroSegLen},
+		{"www.google.com.", "www.google.com.", nil},
+	}
+
+	for _, test := range tests {
+		in := mustNewName(test.in)
+		want := mustNewName(test.want)
+		buf, err := in.pack(make([]byte, 0, 30), map[string]int{}, 0)
+		if err != test.err {
+			t.Errorf("Packing of %q: got err = %v, want err = %v", test.in, err, test.err)
+			continue
+		}
+		if test.err != nil {
+			continue
+		}
+		var got Name
+		n, err := got.unpack(buf, 0)
+		if err != nil {
+			t.Errorf("Unpacking for %q failed: %v", test.in, err)
+			continue
+		}
+		if n != len(buf) {
+			t.Errorf(
+				"Unpacked different amount than packed for %q: got n = %d, want = %d",
+				test.in,
+				n,
+				len(buf),
+			)
+		}
+		if got != want {
+			t.Errorf("Unpacking packing of %q: got = %#v, want = %#v", test.in, got, want)
+		}
+	}
+}
+
+func TestIncompressibleName(t *testing.T) {
+	name := mustNewName("example.com.")
+	compression := map[string]int{}
+	buf, err := name.pack(make([]byte, 0, 100), compression, 0)
+	if err != nil {
+		t.Fatal("First packing failed:", err)
+	}
+	buf, err = name.pack(buf, compression, 0)
+	if err != nil {
+		t.Fatal("Second packing failed:", err)
+	}
+	var n1 Name
+	off, err := n1.unpackCompressed(buf, 0, false /* allowCompression */)
+	if err != nil {
+		t.Fatal("Unpacking incompressible name without pointers failed:", err)
+	}
+	var n2 Name
+	if _, err := n2.unpackCompressed(buf, off, false /* allowCompression */); err != errCompressedSRV {
+		t.Errorf("Unpacking compressed incompressible name with pointers: got err = %v, want = %v", err, errCompressedSRV)
+	}
+}
+
+func checkErrorPrefix(err error, prefix string) bool {
+	e, ok := err.(*nestedError)
+	return ok && e.s == prefix
+}
+
+func TestHeaderUnpackError(t *testing.T) {
+	wants := []string{
+		"id",
+		"bits",
+		"questions",
+		"answers",
+		"authorities",
+		"additionals",
+	}
+	var buf []byte
+	var h header
+	for _, want := range wants {
+		n, err := h.unpack(buf, 0)
+		if n != 0 || !checkErrorPrefix(err, want) {
+			t.Errorf("got h.unpack([%d]byte, 0) = %d, %v, want = 0, %s", len(buf), n, err, want)
+		}
+		buf = append(buf, 0, 0)
+	}
+}
+
+func TestParserStart(t *testing.T) {
+	const want = "unpacking header"
+	var p Parser
+	for i := 0; i <= 1; i++ {
+		_, err := p.Start([]byte{})
+		if !checkErrorPrefix(err, want) {
+			t.Errorf("got p.Start(nil) = _, %v, want = _, %s", err, want)
+		}
+	}
+}
+
+func TestResourceNotStarted(t *testing.T) {
+	tests := []struct {
+		name string
+		fn   func(*Parser) error
+	}{
+		{"CNAMEResource", func(p *Parser) error { _, err := p.CNAMEResource(); return err }},
+		{"MXResource", func(p *Parser) error { _, err := p.MXResource(); return err }},
+		{"NSResource", func(p *Parser) error { _, err := p.NSResource(); return err }},
+		{"PTRResource", func(p *Parser) error { _, err := p.PTRResource(); return err }},
+		{"SOAResource", func(p *Parser) error { _, err := p.SOAResource(); return err }},
+		{"TXTResource", func(p *Parser) error { _, err := p.TXTResource(); return err }},
+		{"SRVResource", func(p *Parser) error { _, err := p.SRVResource(); return err }},
+		{"AResource", func(p *Parser) error { _, err := p.AResource(); return err }},
+		{"AAAAResource", func(p *Parser) error { _, err := p.AAAAResource(); return err }},
+	}
+
+	for _, test := range tests {
+		if err := test.fn(&Parser{}); err != ErrNotStarted {
+			t.Errorf("got _, %v = p.%s(), want = _, %v", err, test.name, ErrNotStarted)
+		}
+	}
+}
+
+func TestDNSPackUnpack(t *testing.T) {
+	wants := []Message{
+		{
+			Questions: []Question{
+				{
+					Name:  mustNewName("."),
+					Type:  TypeAAAA,
+					Class: ClassINET,
+				},
+			},
+			Answers:     []Resource{},
+			Authorities: []Resource{},
+			Additionals: []Resource{},
+		},
+		largeTestMsg(),
+	}
+	for i, want := range wants {
+		b, err := want.Pack()
+		if err != nil {
+			t.Fatalf("%d: packing failed: %v", i, err)
+		}
+		var got Message
+		err = got.Unpack(b)
+		if err != nil {
+			t.Fatalf("%d: unpacking failed: %v", i, err)
+		}
+		if !reflect.DeepEqual(got, want) {
+			t.Errorf("%d: got = %+v, want = %+v", i, &got, &want)
+		}
+	}
+}
+
+func TestDNSAppendPackUnpack(t *testing.T) {
+	wants := []Message{
+		{
+			Questions: []Question{
+				{
+					Name:  mustNewName("."),
+					Type:  TypeAAAA,
+					Class: ClassINET,
+				},
+			},
+			Answers:     []Resource{},
+			Authorities: []Resource{},
+			Additionals: []Resource{},
+		},
+		largeTestMsg(),
+	}
+	for i, want := range wants {
+		b := make([]byte, 2, 514)
+		b, err := want.AppendPack(b)
+		if err != nil {
+			t.Fatalf("%d: packing failed: %v", i, err)
+		}
+		b = b[2:]
+		var got Message
+		err = got.Unpack(b)
+		if err != nil {
+			t.Fatalf("%d: unpacking failed: %v", i, err)
+		}
+		if !reflect.DeepEqual(got, want) {
+			t.Errorf("%d: got = %+v, want = %+v", i, &got, &want)
+		}
+	}
+}
+
+func TestSkipAll(t *testing.T) {
+	msg := largeTestMsg()
+	buf, err := msg.Pack()
+	if err != nil {
+		t.Fatal("Packing large test message:", err)
+	}
+	var p Parser
+	if _, err := p.Start(buf); err != nil {
+		t.Fatal(err)
+	}
+
+	tests := []struct {
+		name string
+		f    func() error
+	}{
+		{"SkipAllQuestions", p.SkipAllQuestions},
+		{"SkipAllAnswers", p.SkipAllAnswers},
+		{"SkipAllAuthorities", p.SkipAllAuthorities},
+		{"SkipAllAdditionals", p.SkipAllAdditionals},
+	}
+	for _, test := range tests {
+		for i := 1; i <= 3; i++ {
+			if err := test.f(); err != nil {
+				t.Errorf("Call #%d to %s(): %v", i, test.name, err)
+			}
+		}
+	}
+}
+
+func TestSkipEach(t *testing.T) {
+	msg := smallTestMsg()
+
+	buf, err := msg.Pack()
+	if err != nil {
+		t.Fatal("Packing test message:", err)
+	}
+	var p Parser
+	if _, err := p.Start(buf); err != nil {
+		t.Fatal(err)
+	}
+
+	tests := []struct {
+		name string
+		f    func() error
+	}{
+		{"SkipQuestion", p.SkipQuestion},
+		{"SkipAnswer", p.SkipAnswer},
+		{"SkipAuthority", p.SkipAuthority},
+		{"SkipAdditional", p.SkipAdditional},
+	}
+	for _, test := range tests {
+		if err := test.f(); err != nil {
+			t.Errorf("First call: got %s() = %v, want = %v", test.name, err, nil)
+		}
+		if err := test.f(); err != ErrSectionDone {
+			t.Errorf("Second call: got %s() = %v, want = %v", test.name, err, ErrSectionDone)
+		}
+	}
+}
+
+func TestSkipAfterRead(t *testing.T) {
+	msg := smallTestMsg()
+
+	buf, err := msg.Pack()
+	if err != nil {
+		t.Fatal("Packing test message:", err)
+	}
+	var p Parser
+	if _, err := p.Start(buf); err != nil {
+		t.Fatal(err)
+	}
+
+	tests := []struct {
+		name string
+		skip func() error
+		read func() error
+	}{
+		{"Question", p.SkipQuestion, func() error { _, err := p.Question(); return err }},
+		{"Answer", p.SkipAnswer, func() error { _, err := p.Answer(); return err }},
+		{"Authority", p.SkipAuthority, func() error { _, err := p.Authority(); return err }},
+		{"Additional", p.SkipAdditional, func() error { _, err := p.Additional(); return err }},
+	}
+	for _, test := range tests {
+		if err := test.read(); err != nil {
+			t.Errorf("Got %s() = _, %v, want = _, %v", test.name, err, nil)
+		}
+		if err := test.skip(); err != ErrSectionDone {
+			t.Errorf("Got Skip%s() = %v, want = %v", test.name, err, ErrSectionDone)
+		}
+	}
+}
+
+func TestSkipNotStarted(t *testing.T) {
+	var p Parser
+
+	tests := []struct {
+		name string
+		f    func() error
+	}{
+		{"SkipAllQuestions", p.SkipAllQuestions},
+		{"SkipAllAnswers", p.SkipAllAnswers},
+		{"SkipAllAuthorities", p.SkipAllAuthorities},
+		{"SkipAllAdditionals", p.SkipAllAdditionals},
+	}
+	for _, test := range tests {
+		if err := test.f(); err != ErrNotStarted {
+			t.Errorf("Got %s() = %v, want = %v", test.name, err, ErrNotStarted)
+		}
+	}
+}
+
+func TestTooManyRecords(t *testing.T) {
+	const recs = int(^uint16(0)) + 1
+	tests := []struct {
+		name string
+		msg  Message
+		want error
+	}{
+		{
+			"Questions",
+			Message{
+				Questions: make([]Question, recs),
+			},
+			errTooManyQuestions,
+		},
+		{
+			"Answers",
+			Message{
+				Answers: make([]Resource, recs),
+			},
+			errTooManyAnswers,
+		},
+		{
+			"Authorities",
+			Message{
+				Authorities: make([]Resource, recs),
+			},
+			errTooManyAuthorities,
+		},
+		{
+			"Additionals",
+			Message{
+				Additionals: make([]Resource, recs),
+			},
+			errTooManyAdditionals,
+		},
+	}
+
+	for _, test := range tests {
+		if _, got := test.msg.Pack(); got != test.want {
+			t.Errorf("Packing %d %s: got = %v, want = %v", recs, test.name, got, test.want)
+		}
+	}
+}
+
+func TestVeryLongTxt(t *testing.T) {
+	want := Resource{
+		ResourceHeader{
+			Name:  mustNewName("foo.bar.example.com."),
+			Type:  TypeTXT,
+			Class: ClassINET,
+		},
+		&TXTResource{[]string{
+			"",
+			"",
+			"foo bar",
+			"",
+			"www.example.com",
+			"www.example.com.",
+			strings.Repeat(".", 255),
+		}},
+	}
+	buf, err := want.pack(make([]byte, 0, 8000), map[string]int{}, 0)
+	if err != nil {
+		t.Fatal("Packing failed:", err)
+	}
+	var got Resource
+	off, err := got.Header.unpack(buf, 0)
+	if err != nil {
+		t.Fatal("Unpacking ResourceHeader failed:", err)
+	}
+	body, n, err := unpackResourceBody(buf, off, got.Header)
+	if err != nil {
+		t.Fatal("Unpacking failed:", err)
+	}
+	got.Body = body
+	if n != len(buf) {
+		t.Errorf("Unpacked different amount than packed: got n = %d, want = %d", n, len(buf))
+	}
+	if !reflect.DeepEqual(got, want) {
+		t.Errorf("Got = %#v, want = %#v", got, want)
+	}
+}
+
+func TestTooLongTxt(t *testing.T) {
+	rb := TXTResource{[]string{strings.Repeat(".", 256)}}
+	if _, err := rb.pack(make([]byte, 0, 8000), map[string]int{}, 0); err != errStringTooLong {
+		t.Errorf("Packing TXTRecord with 256 character string: got err = %v, want = %v", err, errStringTooLong)
+	}
+}
+
+func TestStartAppends(t *testing.T) {
+	buf := make([]byte, 2, 514)
+	wantBuf := []byte{4, 44}
+	copy(buf, wantBuf)
+
+	b := NewBuilder(buf, Header{})
+	b.EnableCompression()
+
+	buf, err := b.Finish()
+	if err != nil {
+		t.Fatal("Building failed:", err)
+	}
+	if got, want := len(buf), headerLen+2; got != want {
+		t.Errorf("Got len(buf} = %d, want = %d", got, want)
+	}
+	if string(buf[:2]) != string(wantBuf) {
+		t.Errorf("Original data not preserved, got = %v, want = %v", buf[:2], wantBuf)
+	}
+}
+
+func TestStartError(t *testing.T) {
+	tests := []struct {
+		name string
+		fn   func(*Builder) error
+	}{
+		{"Questions", func(b *Builder) error { return b.StartQuestions() }},
+		{"Answers", func(b *Builder) error { return b.StartAnswers() }},
+		{"Authorities", func(b *Builder) error { return b.StartAuthorities() }},
+		{"Additionals", func(b *Builder) error { return b.StartAdditionals() }},
+	}
+
+	envs := []struct {
+		name string
+		fn   func() *Builder
+		want error
+	}{
+		{"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
+		{"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
+	}
+
+	for _, env := range envs {
+		for _, test := range tests {
+			if got := test.fn(env.fn()); got != env.want {
+				t.Errorf("got Builder{%s}.Start%s = %v, want = %v", env.name, test.name, got, env.want)
+			}
+		}
+	}
+}
+
+func TestBuilderResourceError(t *testing.T) {
+	tests := []struct {
+		name string
+		fn   func(*Builder) error
+	}{
+		{"CNAMEResource", func(b *Builder) error { return b.CNAMEResource(ResourceHeader{}, CNAMEResource{}) }},
+		{"MXResource", func(b *Builder) error { return b.MXResource(ResourceHeader{}, MXResource{}) }},
+		{"NSResource", func(b *Builder) error { return b.NSResource(ResourceHeader{}, NSResource{}) }},
+		{"PTRResource", func(b *Builder) error { return b.PTRResource(ResourceHeader{}, PTRResource{}) }},
+		{"SOAResource", func(b *Builder) error { return b.SOAResource(ResourceHeader{}, SOAResource{}) }},
+		{"TXTResource", func(b *Builder) error { return b.TXTResource(ResourceHeader{}, TXTResource{}) }},
+		{"SRVResource", func(b *Builder) error { return b.SRVResource(ResourceHeader{}, SRVResource{}) }},
+		{"AResource", func(b *Builder) error { return b.AResource(ResourceHeader{}, AResource{}) }},
+		{"AAAAResource", func(b *Builder) error { return b.AAAAResource(ResourceHeader{}, AAAAResource{}) }},
+	}
+
+	envs := []struct {
+		name string
+		fn   func() *Builder
+		want error
+	}{
+		{"sectionNotStarted", func() *Builder { return &Builder{section: sectionNotStarted} }, ErrNotStarted},
+		{"sectionHeader", func() *Builder { return &Builder{section: sectionHeader} }, ErrNotStarted},
+		{"sectionQuestions", func() *Builder { return &Builder{section: sectionQuestions} }, ErrNotStarted},
+		{"sectionDone", func() *Builder { return &Builder{section: sectionDone} }, ErrSectionDone},
+	}
+
+	for _, env := range envs {
+		for _, test := range tests {
+			if got := test.fn(env.fn()); got != env.want {
+				t.Errorf("got Builder{%s}.%s = %v, want = %v", env.name, test.name, got, env.want)
+			}
+		}
+	}
+}
+
+func TestFinishError(t *testing.T) {
+	var b Builder
+	want := ErrNotStarted
+	if _, got := b.Finish(); got != want {
+		t.Errorf("got Builder{}.Finish() = %v, want = %v", got, want)
+	}
+}
+
+func TestBuilder(t *testing.T) {
+	msg := largeTestMsg()
+	want, err := msg.Pack()
+	if err != nil {
+		t.Fatal("Packing without builder:", err)
+	}
+
+	b := NewBuilder(nil, msg.Header)
+	b.EnableCompression()
+
+	if err := b.StartQuestions(); err != nil {
+		t.Fatal("b.StartQuestions():", err)
+	}
+	for _, q := range msg.Questions {
+		if err := b.Question(q); err != nil {
+			t.Fatalf("b.Question(%#v): %v", q, err)
+		}
+	}
+
+	if err := b.StartAnswers(); err != nil {
+		t.Fatal("b.StartAnswers():", err)
+	}
+	for _, a := range msg.Answers {
+		switch a.Header.Type {
+		case TypeA:
+			if err := b.AResource(a.Header, *a.Body.(*AResource)); err != nil {
+				t.Fatalf("b.AResource(%#v): %v", a, err)
+			}
+		case TypeNS:
+			if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
+				t.Fatalf("b.NSResource(%#v): %v", a, err)
+			}
+		case TypeCNAME:
+			if err := b.CNAMEResource(a.Header, *a.Body.(*CNAMEResource)); err != nil {
+				t.Fatalf("b.CNAMEResource(%#v): %v", a, err)
+			}
+		case TypeSOA:
+			if err := b.SOAResource(a.Header, *a.Body.(*SOAResource)); err != nil {
+				t.Fatalf("b.SOAResource(%#v): %v", a, err)
+			}
+		case TypePTR:
+			if err := b.PTRResource(a.Header, *a.Body.(*PTRResource)); err != nil {
+				t.Fatalf("b.PTRResource(%#v): %v", a, err)
+			}
+		case TypeMX:
+			if err := b.MXResource(a.Header, *a.Body.(*MXResource)); err != nil {
+				t.Fatalf("b.MXResource(%#v): %v", a, err)
+			}
+		case TypeTXT:
+			if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
+				t.Fatalf("b.TXTResource(%#v): %v", a, err)
+			}
+		case TypeAAAA:
+			if err := b.AAAAResource(a.Header, *a.Body.(*AAAAResource)); err != nil {
+				t.Fatalf("b.AAAAResource(%#v): %v", a, err)
+			}
+		case TypeSRV:
+			if err := b.SRVResource(a.Header, *a.Body.(*SRVResource)); err != nil {
+				t.Fatalf("b.SRVResource(%#v): %v", a, err)
+			}
+		}
+	}
+
+	if err := b.StartAuthorities(); err != nil {
+		t.Fatal("b.StartAuthorities():", err)
+	}
+	for _, a := range msg.Authorities {
+		if err := b.NSResource(a.Header, *a.Body.(*NSResource)); err != nil {
+			t.Fatalf("b.NSResource(%#v): %v", a, err)
+		}
+	}
+
+	if err := b.StartAdditionals(); err != nil {
+		t.Fatal("b.StartAdditionals():", err)
+	}
+	for _, a := range msg.Additionals {
+		if err := b.TXTResource(a.Header, *a.Body.(*TXTResource)); err != nil {
+			t.Fatalf("b.TXTResource(%#v): %v", a, err)
+		}
+	}
+
+	got, err := b.Finish()
+	if err != nil {
+		t.Fatal("b.Finish():", err)
+	}
+	if !bytes.Equal(got, want) {
+		t.Fatalf("Got from Builder: %#v\nwant = %#v", got, want)
+	}
+}
+
+func TestResourcePack(t *testing.T) {
+	for _, tt := range []struct {
+		m   Message
+		err error
+	}{
+		{
+			Message{
+				Questions: []Question{
+					{
+						Name:  mustNewName("."),
+						Type:  TypeAAAA,
+						Class: ClassINET,
+					},
+				},
+				Answers: []Resource{{ResourceHeader{}, nil}},
+			},
+			&nestedError{"packing Answer", errNilResouceBody},
+		},
+		{
+			Message{
+				Questions: []Question{
+					{
+						Name:  mustNewName("."),
+						Type:  TypeAAAA,
+						Class: ClassINET,
+					},
+				},
+				Authorities: []Resource{{ResourceHeader{}, (*NSResource)(nil)}},
+			},
+			&nestedError{"packing Authority",
+				&nestedError{"ResourceHeader",
+					&nestedError{"Name", errNonCanonicalName},
+				},
+			},
+		},
+		{
+			Message{
+				Questions: []Question{
+					{
+						Name:  mustNewName("."),
+						Type:  TypeA,
+						Class: ClassINET,
+					},
+				},
+				Additionals: []Resource{{ResourceHeader{}, nil}},
+			},
+			&nestedError{"packing Additional", errNilResouceBody},
+		},
+	} {
+		_, err := tt.m.Pack()
+		if !reflect.DeepEqual(err, tt.err) {
+			t.Errorf("got %v for %v; want %v", err, tt.m, tt.err)
+		}
+	}
+}
+
+func benchmarkParsingSetup() ([]byte, error) {
+	name := mustNewName("foo.bar.example.com.")
+	msg := Message{
+		Header: Header{Response: true, Authoritative: true},
+		Questions: []Question{
+			{
+				Name:  name,
+				Type:  TypeA,
+				Class: ClassINET,
+			},
+		},
+		Answers: []Resource{
+			{
+				ResourceHeader{
+					Name:  name,
+					Class: ClassINET,
+				},
+				&AResource{[4]byte{}},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Class: ClassINET,
+				},
+				&AAAAResource{[16]byte{}},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Class: ClassINET,
+				},
+				&CNAMEResource{name},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Class: ClassINET,
+				},
+				&NSResource{name},
+			},
+		},
+	}
+
+	buf, err := msg.Pack()
+	if err != nil {
+		return nil, fmt.Errorf("msg.Pack(): %v", err)
+	}
+	return buf, nil
+}
+
+func benchmarkParsing(tb testing.TB, buf []byte) {
+	var p Parser
+	if _, err := p.Start(buf); err != nil {
+		tb.Fatal("p.Start(buf):", err)
+	}
+
+	for {
+		_, err := p.Question()
+		if err == ErrSectionDone {
+			break
+		}
+		if err != nil {
+			tb.Fatal("p.Question():", err)
+		}
+	}
+
+	for {
+		h, err := p.AnswerHeader()
+		if err == ErrSectionDone {
+			break
+		}
+		if err != nil {
+			panic(err)
+		}
+
+		switch h.Type {
+		case TypeA:
+			if _, err := p.AResource(); err != nil {
+				tb.Fatal("p.AResource():", err)
+			}
+		case TypeAAAA:
+			if _, err := p.AAAAResource(); err != nil {
+				tb.Fatal("p.AAAAResource():", err)
+			}
+		case TypeCNAME:
+			if _, err := p.CNAMEResource(); err != nil {
+				tb.Fatal("p.CNAMEResource():", err)
+			}
+		case TypeNS:
+			if _, err := p.NSResource(); err != nil {
+				tb.Fatal("p.NSResource():", err)
+			}
+		default:
+			tb.Fatalf("unknown type: %T", h)
+		}
+	}
+}
+
+func BenchmarkParsing(b *testing.B) {
+	buf, err := benchmarkParsingSetup()
+	if err != nil {
+		b.Fatal(err)
+	}
+
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		benchmarkParsing(b, buf)
+	}
+}
+
+func TestParsingAllocs(t *testing.T) {
+	buf, err := benchmarkParsingSetup()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if allocs := testing.AllocsPerRun(100, func() { benchmarkParsing(t, buf) }); allocs > 0.5 {
+		t.Errorf("Allocations during parsing: got = %f, want ~0", allocs)
+	}
+}
+
+func benchmarkBuildingSetup() (Name, []byte) {
+	name := mustNewName("foo.bar.example.com.")
+	buf := make([]byte, 0, packStartingCap)
+	return name, buf
+}
+
+func benchmarkBuilding(tb testing.TB, name Name, buf []byte) {
+	bld := NewBuilder(buf, Header{Response: true, Authoritative: true})
+
+	if err := bld.StartQuestions(); err != nil {
+		tb.Fatal("bld.StartQuestions():", err)
+	}
+	q := Question{
+		Name:  name,
+		Type:  TypeA,
+		Class: ClassINET,
+	}
+	if err := bld.Question(q); err != nil {
+		tb.Fatalf("bld.Question(%+v): %v", q, err)
+	}
+
+	hdr := ResourceHeader{
+		Name:  name,
+		Class: ClassINET,
+	}
+	if err := bld.StartAnswers(); err != nil {
+		tb.Fatal("bld.StartQuestions():", err)
+	}
+
+	ar := AResource{[4]byte{}}
+	if err := bld.AResource(hdr, ar); err != nil {
+		tb.Fatalf("bld.AResource(%+v, %+v): %v", hdr, ar, err)
+	}
+
+	aaar := AAAAResource{[16]byte{}}
+	if err := bld.AAAAResource(hdr, aaar); err != nil {
+		tb.Fatalf("bld.AAAAResource(%+v, %+v): %v", hdr, aaar, err)
+	}
+
+	cnr := CNAMEResource{name}
+	if err := bld.CNAMEResource(hdr, cnr); err != nil {
+		tb.Fatalf("bld.CNAMEResource(%+v, %+v): %v", hdr, cnr, err)
+	}
+
+	nsr := NSResource{name}
+	if err := bld.NSResource(hdr, nsr); err != nil {
+		tb.Fatalf("bld.NSResource(%+v, %+v): %v", hdr, nsr, err)
+	}
+
+	if _, err := bld.Finish(); err != nil {
+		tb.Fatal("bld.Finish():", err)
+	}
+}
+
+func BenchmarkBuilding(b *testing.B) {
+	name, buf := benchmarkBuildingSetup()
+	b.ReportAllocs()
+	for i := 0; i < b.N; i++ {
+		benchmarkBuilding(b, name, buf)
+	}
+}
+
+func TestBuildingAllocs(t *testing.T) {
+	name, buf := benchmarkBuildingSetup()
+	if allocs := testing.AllocsPerRun(100, func() { benchmarkBuilding(t, name, buf) }); allocs > 0.5 {
+		t.Errorf("Allocations during building: got = %f, want ~0", allocs)
+	}
+}
+
+func smallTestMsg() Message {
+	name := mustNewName("example.com.")
+	return Message{
+		Header: Header{Response: true, Authoritative: true},
+		Questions: []Question{
+			{
+				Name:  name,
+				Type:  TypeA,
+				Class: ClassINET,
+			},
+		},
+		Answers: []Resource{
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeA,
+					Class: ClassINET,
+				},
+				&AResource{[4]byte{127, 0, 0, 1}},
+			},
+		},
+		Authorities: []Resource{
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeA,
+					Class: ClassINET,
+				},
+				&AResource{[4]byte{127, 0, 0, 1}},
+			},
+		},
+		Additionals: []Resource{
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeA,
+					Class: ClassINET,
+				},
+				&AResource{[4]byte{127, 0, 0, 1}},
+			},
+		},
+	}
+}
+
+func BenchmarkPack(b *testing.B) {
+	msg := largeTestMsg()
+
+	b.ReportAllocs()
+
+	for i := 0; i < b.N; i++ {
+		if _, err := msg.Pack(); err != nil {
+			b.Fatal(err)
+		}
+	}
+}
+
+func BenchmarkAppendPack(b *testing.B) {
+	msg := largeTestMsg()
+	buf := make([]byte, 0, packStartingCap)
+
+	b.ReportAllocs()
+
+	for i := 0; i < b.N; i++ {
+		if _, err := msg.AppendPack(buf[:0]); err != nil {
+			b.Fatal(err)
+		}
+	}
+}
+
+func largeTestMsg() Message {
+	name := mustNewName("foo.bar.example.com.")
+	return Message{
+		Header: Header{Response: true, Authoritative: true},
+		Questions: []Question{
+			{
+				Name:  name,
+				Type:  TypeA,
+				Class: ClassINET,
+			},
+		},
+		Answers: []Resource{
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeA,
+					Class: ClassINET,
+				},
+				&AResource{[4]byte{127, 0, 0, 1}},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeA,
+					Class: ClassINET,
+				},
+				&AResource{[4]byte{127, 0, 0, 2}},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeAAAA,
+					Class: ClassINET,
+				},
+				&AAAAResource{[16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeCNAME,
+					Class: ClassINET,
+				},
+				&CNAMEResource{mustNewName("alias.example.com.")},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeSOA,
+					Class: ClassINET,
+				},
+				&SOAResource{
+					NS:      mustNewName("ns1.example.com."),
+					MBox:    mustNewName("mb.example.com."),
+					Serial:  1,
+					Refresh: 2,
+					Retry:   3,
+					Expire:  4,
+					MinTTL:  5,
+				},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypePTR,
+					Class: ClassINET,
+				},
+				&PTRResource{mustNewName("ptr.example.com.")},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeMX,
+					Class: ClassINET,
+				},
+				&MXResource{
+					7,
+					mustNewName("mx.example.com."),
+				},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeSRV,
+					Class: ClassINET,
+				},
+				&SRVResource{
+					8,
+					9,
+					11,
+					mustNewName("srv.example.com."),
+				},
+			},
+		},
+		Authorities: []Resource{
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeNS,
+					Class: ClassINET,
+				},
+				&NSResource{mustNewName("ns1.example.com.")},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeNS,
+					Class: ClassINET,
+				},
+				&NSResource{mustNewName("ns2.example.com.")},
+			},
+		},
+		Additionals: []Resource{
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeTXT,
+					Class: ClassINET,
+				},
+				&TXTResource{[]string{"So Long, and Thanks for All the Fish"}},
+			},
+			{
+				ResourceHeader{
+					Name:  name,
+					Type:  TypeTXT,
+					Class: ClassINET,
+				},
+				&TXTResource{[]string{"Hamster Huey and the Gooey Kablooie"}},
+			},
+		},
+	}
+}
diff --git a/libgo/go/golang_org/x/net/http/httpguts/guts.go b/libgo/go/golang_org/x/net/http/httpguts/guts.go
new file mode 100644
index 00000000000..e6cd0ced392
--- /dev/null
+++ b/libgo/go/golang_org/x/net/http/httpguts/guts.go
@@ -0,0 +1,50 @@
+// 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 httpguts provides functions implementing various details
+// of the HTTP specification.
+//
+// This package is shared by the standard library (which vendors it)
+// and x/net/http2. It comes with no API stability promise.
+package httpguts
+
+import (
+	"net/textproto"
+	"strings"
+)
+
+// ValidTrailerHeader reports whether name is a valid header field name to appear
+// in trailers.
+// See RFC 7230, Section 4.1.2
+func ValidTrailerHeader(name string) bool {
+	name = textproto.CanonicalMIMEHeaderKey(name)
+	if strings.HasPrefix(name, "If-") || badTrailer[name] {
+		return false
+	}
+	return true
+}
+
+var badTrailer = map[string]bool{
+	"Authorization":       true,
+	"Cache-Control":       true,
+	"Connection":          true,
+	"Content-Encoding":    true,
+	"Content-Length":      true,
+	"Content-Range":       true,
+	"Content-Type":        true,
+	"Expect":              true,
+	"Host":                true,
+	"Keep-Alive":          true,
+	"Max-Forwards":        true,
+	"Pragma":              true,
+	"Proxy-Authenticate":  true,
+	"Proxy-Authorization": true,
+	"Proxy-Connection":    true,
+	"Range":               true,
+	"Realm":               true,
+	"Te":                  true,
+	"Trailer":             true,
+	"Transfer-Encoding":   true,
+	"Www-Authenticate":    true,
+}
diff --git a/libgo/go/golang_org/x/net/http/httpguts/httplex.go b/libgo/go/golang_org/x/net/http/httpguts/httplex.go
new file mode 100644
index 00000000000..9337435174e
--- /dev/null
+++ b/libgo/go/golang_org/x/net/http/httpguts/httplex.go
@@ -0,0 +1,346 @@
+// 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 httpguts
+
+import (
+	"net"
+	"strings"
+	"unicode/utf8"
+
+	"golang_org/x/net/idna"
+)
+
+var isTokenTable = [127]bool{
+	'!':  true,
+	'#':  true,
+	'$':  true,
+	'%':  true,
+	'&':  true,
+	'\'': true,
+	'*':  true,
+	'+':  true,
+	'-':  true,
+	'.':  true,
+	'0':  true,
+	'1':  true,
+	'2':  true,
+	'3':  true,
+	'4':  true,
+	'5':  true,
+	'6':  true,
+	'7':  true,
+	'8':  true,
+	'9':  true,
+	'A':  true,
+	'B':  true,
+	'C':  true,
+	'D':  true,
+	'E':  true,
+	'F':  true,
+	'G':  true,
+	'H':  true,
+	'I':  true,
+	'J':  true,
+	'K':  true,
+	'L':  true,
+	'M':  true,
+	'N':  true,
+	'O':  true,
+	'P':  true,
+	'Q':  true,
+	'R':  true,
+	'S':  true,
+	'T':  true,
+	'U':  true,
+	'W':  true,
+	'V':  true,
+	'X':  true,
+	'Y':  true,
+	'Z':  true,
+	'^':  true,
+	'_':  true,
+	'`':  true,
+	'a':  true,
+	'b':  true,
+	'c':  true,
+	'd':  true,
+	'e':  true,
+	'f':  true,
+	'g':  true,
+	'h':  true,
+	'i':  true,
+	'j':  true,
+	'k':  true,
+	'l':  true,
+	'm':  true,
+	'n':  true,
+	'o':  true,
+	'p':  true,
+	'q':  true,
+	'r':  true,
+	's':  true,
+	't':  true,
+	'u':  true,
+	'v':  true,
+	'w':  true,
+	'x':  true,
+	'y':  true,
+	'z':  true,
+	'|':  true,
+	'~':  true,
+}
+
+func IsTokenRune(r rune) bool {
+	i := int(r)
+	return i < len(isTokenTable) && isTokenTable[i]
+}
+
+func isNotToken(r rune) bool {
+	return !IsTokenRune(r)
+}
+
+// HeaderValuesContainsToken reports whether any string in values
+// contains the provided token, ASCII case-insensitively.
+func HeaderValuesContainsToken(values []string, token string) bool {
+	for _, v := range values {
+		if headerValueContainsToken(v, token) {
+			return true
+		}
+	}
+	return false
+}
+
+// isOWS reports whether b is an optional whitespace byte, as defined
+// by RFC 7230 section 3.2.3.
+func isOWS(b byte) bool { return b == ' ' || b == '\t' }
+
+// trimOWS returns x with all optional whitespace removes from the
+// beginning and end.
+func trimOWS(x string) string {
+	// TODO: consider using strings.Trim(x, " \t") instead,
+	// if and when it's fast enough. See issue 10292.
+	// But this ASCII-only code will probably always beat UTF-8
+	// aware code.
+	for len(x) > 0 && isOWS(x[0]) {
+		x = x[1:]
+	}
+	for len(x) > 0 && isOWS(x[len(x)-1]) {
+		x = x[:len(x)-1]
+	}
+	return x
+}
+
+// headerValueContainsToken reports whether v (assumed to be a
+// 0#element, in the ABNF extension described in RFC 7230 section 7)
+// contains token amongst its comma-separated tokens, ASCII
+// case-insensitively.
+func headerValueContainsToken(v string, token string) bool {
+	v = trimOWS(v)
+	if comma := strings.IndexByte(v, ','); comma != -1 {
+		return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
+	}
+	return tokenEqual(v, token)
+}
+
+// lowerASCII returns the ASCII lowercase version of b.
+func lowerASCII(b byte) byte {
+	if 'A' <= b && b <= 'Z' {
+		return b + ('a' - 'A')
+	}
+	return b
+}
+
+// tokenEqual reports whether t1 and t2 are equal, ASCII case-insensitively.
+func tokenEqual(t1, t2 string) bool {
+	if len(t1) != len(t2) {
+		return false
+	}
+	for i, b := range t1 {
+		if b >= utf8.RuneSelf {
+			// No UTF-8 or non-ASCII allowed in tokens.
+			return false
+		}
+		if lowerASCII(byte(b)) != lowerASCII(t2[i]) {
+			return false
+		}
+	}
+	return true
+}
+
+// isLWS reports whether b is linear white space, according
+// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
+//      LWS            = [CRLF] 1*( SP | HT )
+func isLWS(b byte) bool { return b == ' ' || b == '\t' }
+
+// isCTL reports whether b is a control byte, according
+// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
+//      CTL            = 
+func isCTL(b byte) bool {
+	const del = 0x7f // a CTL
+	return b < ' ' || b == del
+}
+
+// ValidHeaderFieldName reports whether v is a valid HTTP/1.x header name.
+// HTTP/2 imposes the additional restriction that uppercase ASCII
+// letters are not allowed.
+//
+//  RFC 7230 says:
+//   header-field   = field-name ":" OWS field-value OWS
+//   field-name     = token
+//   token          = 1*tchar
+//   tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
+//           "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
+func ValidHeaderFieldName(v string) bool {
+	if len(v) == 0 {
+		return false
+	}
+	for _, r := range v {
+		if !IsTokenRune(r) {
+			return false
+		}
+	}
+	return true
+}
+
+// ValidHostHeader reports whether h is a valid host header.
+func ValidHostHeader(h string) bool {
+	// The latest spec is actually this:
+	//
+	// http://tools.ietf.org/html/rfc7230#section-5.4
+	//     Host = uri-host [ ":" port ]
+	//
+	// Where uri-host is:
+	//     http://tools.ietf.org/html/rfc3986#section-3.2.2
+	//
+	// But we're going to be much more lenient for now and just
+	// search for any byte that's not a valid byte in any of those
+	// expressions.
+	for i := 0; i < len(h); i++ {
+		if !validHostByte[h[i]] {
+			return false
+		}
+	}
+	return true
+}
+
+// See the validHostHeader comment.
+var validHostByte = [256]bool{
+	'0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true,
+	'8': true, '9': true,
+
+	'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true,
+	'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true,
+	'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true,
+	'y': true, 'z': true,
+
+	'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true,
+	'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true,
+	'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true,
+	'Y': true, 'Z': true,
+
+	'!':  true, // sub-delims
+	'$':  true, // sub-delims
+	'%':  true, // pct-encoded (and used in IPv6 zones)
+	'&':  true, // sub-delims
+	'(':  true, // sub-delims
+	')':  true, // sub-delims
+	'*':  true, // sub-delims
+	'+':  true, // sub-delims
+	',':  true, // sub-delims
+	'-':  true, // unreserved
+	'.':  true, // unreserved
+	':':  true, // IPv6address + Host expression's optional port
+	';':  true, // sub-delims
+	'=':  true, // sub-delims
+	'[':  true,
+	'\'': true, // sub-delims
+	']':  true,
+	'_':  true, // unreserved
+	'~':  true, // unreserved
+}
+
+// ValidHeaderFieldValue reports whether v is a valid "field-value" according to
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 :
+//
+//        message-header = field-name ":" [ field-value ]
+//        field-value    = *( field-content | LWS )
+//        field-content  = 
+//
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 :
+//
+//        TEXT           = 
+//        LWS            = [CRLF] 1*( SP | HT )
+//        CTL            = 
+//
+// RFC 7230 says:
+//  field-value    = *( field-content / obs-fold )
+//  obj-fold       =  N/A to http2, and deprecated
+//  field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
+//  field-vchar    = VCHAR / obs-text
+//  obs-text       = %x80-FF
+//  VCHAR          = "any visible [USASCII] character"
+//
+// http2 further says: "Similarly, HTTP/2 allows header field values
+// that are not valid. While most of the values that can be encoded
+// will not alter header field parsing, carriage return (CR, ASCII
+// 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII
+// 0x0) might be exploited by an attacker if they are translated
+// verbatim. Any request or response that contains a character not
+// permitted in a header field value MUST be treated as malformed
+// (Section 8.1.2.6). Valid characters are defined by the
+// field-content ABNF rule in Section 3.2 of [RFC7230]."
+//
+// This function does not (yet?) properly handle the rejection of
+// strings that begin or end with SP or HTAB.
+func ValidHeaderFieldValue(v string) bool {
+	for i := 0; i < len(v); i++ {
+		b := v[i]
+		if isCTL(b) && !isLWS(b) {
+			return false
+		}
+	}
+	return true
+}
+
+func isASCII(s string) bool {
+	for i := 0; i < len(s); i++ {
+		if s[i] >= utf8.RuneSelf {
+			return false
+		}
+	}
+	return true
+}
+
+// PunycodeHostPort returns the IDNA Punycode version
+// of the provided "host" or "host:port" string.
+func PunycodeHostPort(v string) (string, error) {
+	if isASCII(v) {
+		return v, nil
+	}
+
+	host, port, err := net.SplitHostPort(v)
+	if err != nil {
+		// The input 'v' argument was just a "host" argument,
+		// without a port. This error should not be returned
+		// to the caller.
+		host = v
+		port = ""
+	}
+	host, err = idna.ToASCII(host)
+	if err != nil {
+		// Non-UTF-8? Not representable in Punycode, in any
+		// case.
+		return "", err
+	}
+	if port == "" {
+		return host, nil
+	}
+	return net.JoinHostPort(host, port), nil
+}
diff --git a/libgo/go/golang_org/x/net/http/httpguts/httplex_test.go b/libgo/go/golang_org/x/net/http/httpguts/httplex_test.go
new file mode 100644
index 00000000000..a2c57f3927e
--- /dev/null
+++ b/libgo/go/golang_org/x/net/http/httpguts/httplex_test.go
@@ -0,0 +1,119 @@
+// 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 httpguts
+
+import (
+	"testing"
+)
+
+func isChar(c rune) bool { return c <= 127 }
+
+func isCtl(c rune) bool { return c <= 31 || c == 127 }
+
+func isSeparator(c rune) bool {
+	switch c {
+	case '(', ')', '<', '>', '@', ',', ';', ':', '\\', '"', '/', '[', ']', '?', '=', '{', '}', ' ', '\t':
+		return true
+	}
+	return false
+}
+
+func TestIsToken(t *testing.T) {
+	for i := 0; i <= 130; i++ {
+		r := rune(i)
+		expected := isChar(r) && !isCtl(r) && !isSeparator(r)
+		if IsTokenRune(r) != expected {
+			t.Errorf("isToken(0x%x) = %v", r, !expected)
+		}
+	}
+}
+
+func TestHeaderValuesContainsToken(t *testing.T) {
+	tests := []struct {
+		vals  []string
+		token string
+		want  bool
+	}{
+		{
+			vals:  []string{"foo"},
+			token: "foo",
+			want:  true,
+		},
+		{
+			vals:  []string{"bar", "foo"},
+			token: "foo",
+			want:  true,
+		},
+		{
+			vals:  []string{"foo"},
+			token: "FOO",
+			want:  true,
+		},
+		{
+			vals:  []string{"foo"},
+			token: "bar",
+			want:  false,
+		},
+		{
+			vals:  []string{" foo "},
+			token: "FOO",
+			want:  true,
+		},
+		{
+			vals:  []string{"foo,bar"},
+			token: "FOO",
+			want:  true,
+		},
+		{
+			vals:  []string{"bar,foo,bar"},
+			token: "FOO",
+			want:  true,
+		},
+		{
+			vals:  []string{"bar , foo"},
+			token: "FOO",
+			want:  true,
+		},
+		{
+			vals:  []string{"foo ,bar "},
+			token: "FOO",
+			want:  true,
+		},
+		{
+			vals:  []string{"bar, foo ,bar"},
+			token: "FOO",
+			want:  true,
+		},
+		{
+			vals:  []string{"bar , foo"},
+			token: "FOO",
+			want:  true,
+		},
+	}
+	for _, tt := range tests {
+		got := HeaderValuesContainsToken(tt.vals, tt.token)
+		if got != tt.want {
+			t.Errorf("headerValuesContainsToken(%q, %q) = %v; want %v", tt.vals, tt.token, got, tt.want)
+		}
+	}
+}
+
+func TestPunycodeHostPort(t *testing.T) {
+	tests := []struct {
+		in, want string
+	}{
+		{"www.google.com", "www.google.com"},
+		{"гофер.рф", "xn--c1ae0ajs.xn--p1ai"},
+		{"bücher.de", "xn--bcher-kva.de"},
+		{"bücher.de:8080", "xn--bcher-kva.de:8080"},
+		{"[1::6]:8080", "[1::6]:8080"},
+	}
+	for _, tt := range tests {
+		got, err := PunycodeHostPort(tt.in)
+		if tt.want != got || err != nil {
+			t.Errorf("PunycodeHostPort(%q) = %q, %v, want %q, nil", tt.in, got, err, tt.want)
+		}
+	}
+}
diff --git a/libgo/go/golang_org/x/net/http/httpproxy/export_test.go b/libgo/go/golang_org/x/net/http/httpproxy/export_test.go
new file mode 100644
index 00000000000..5d30018fbd2
--- /dev/null
+++ b/libgo/go/golang_org/x/net/http/httpproxy/export_test.go
@@ -0,0 +1,13 @@
+// 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 httpproxy
+
+func ExportUseProxy(cfg *Config, host string) bool {
+	cfg1 := &config{
+		Config: *cfg,
+	}
+	cfg1.init()
+	return cfg1.useProxy(host)
+}
diff --git a/libgo/go/golang_org/x/net/http/httpproxy/proxy.go b/libgo/go/golang_org/x/net/http/httpproxy/proxy.go
new file mode 100644
index 00000000000..0409f4340c3
--- /dev/null
+++ b/libgo/go/golang_org/x/net/http/httpproxy/proxy.go
@@ -0,0 +1,370 @@
+// 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 httpproxy provides support for HTTP proxy determination
+// based on environment variables, as provided by net/http's
+// ProxyFromEnvironment function.
+//
+// The API is not subject to the Go 1 compatibility promise and may change at
+// any time.
+package httpproxy
+
+import (
+	"errors"
+	"fmt"
+	"net"
+	"net/url"
+	"os"
+	"strings"
+	"unicode/utf8"
+
+	"golang_org/x/net/idna"
+)
+
+// Config holds configuration for HTTP proxy settings. See
+// FromEnvironment for details.
+type Config struct {
+	// HTTPProxy represents the value of the HTTP_PROXY or
+	// http_proxy environment variable. It will be used as the proxy
+	// URL for HTTP requests and HTTPS requests unless overridden by
+	// HTTPSProxy or NoProxy.
+	HTTPProxy string
+
+	// HTTPSProxy represents the HTTPS_PROXY or https_proxy
+	// environment variable. It will be used as the proxy URL for
+	// HTTPS requests unless overridden by NoProxy.
+	HTTPSProxy string
+
+	// NoProxy represents the NO_PROXY or no_proxy environment
+	// variable. It specifies a string that contains comma-separated values
+	// specifying hosts that should be excluded from proxying. Each value is
+	// represented by an IP address prefix (1.2.3.4), an IP address prefix in
+	// CIDR notation (1.2.3.4/8), a domain name, or a special DNS label (*).
+	// An IP address prefix and domain name can also include a literal port
+	// number (1.2.3.4:80).
+	// A domain name matches that name and all subdomains. A domain name with
+	// a leading "." matches subdomains only. For example "foo.com" matches
+	// "foo.com" and "bar.foo.com"; ".y.com" matches "x.y.com" but not "y.com".
+	// A single asterisk (*) indicates that no proxying should be done.
+	// A best effort is made to parse the string and errors are
+	// ignored.
+	NoProxy string
+
+	// CGI holds whether the current process is running
+	// as a CGI handler (FromEnvironment infers this from the
+	// presence of a REQUEST_METHOD environment variable).
+	// When this is set, ProxyForURL will return an error
+	// when HTTPProxy applies, because a client could be
+	// setting HTTP_PROXY maliciously. See https://golang.org/s/cgihttpproxy.
+	CGI bool
+}
+
+// config holds the parsed configuration for HTTP proxy settings.
+type config struct {
+	// Config represents the original configuration as defined above.
+	Config
+
+	// httpsProxy is the parsed URL of the HTTPSProxy if defined.
+	httpsProxy *url.URL
+
+	// httpProxy is the parsed URL of the HTTPProxy if defined.
+	httpProxy *url.URL
+
+	// ipMatchers represent all values in the NoProxy that are IP address
+	// prefixes or an IP address in CIDR notation.
+	ipMatchers []matcher
+
+	// domainMatchers represent all values in the NoProxy that are a domain
+	// name or hostname & domain name
+	domainMatchers []matcher
+}
+
+// FromEnvironment returns a Config instance populated from the
+// environment variables HTTP_PROXY, HTTPS_PROXY and NO_PROXY (or the
+// lowercase versions thereof). HTTPS_PROXY takes precedence over
+// HTTP_PROXY for https requests.
+//
+// The environment values may be either a complete URL or a
+// "host[:port]", in which case the "http" scheme is assumed. An error
+// is returned if the value is a different form.
+func FromEnvironment() *Config {
+	return &Config{
+		HTTPProxy:  getEnvAny("HTTP_PROXY", "http_proxy"),
+		HTTPSProxy: getEnvAny("HTTPS_PROXY", "https_proxy"),
+		NoProxy:    getEnvAny("NO_PROXY", "no_proxy"),
+		CGI:        os.Getenv("REQUEST_METHOD") != "",
+	}
+}
+
+func getEnvAny(names ...string) string {
+	for _, n := range names {
+		if val := os.Getenv(n); val != "" {
+			return val
+		}
+	}
+	return ""
+}
+
+// ProxyFunc returns a function that determines the proxy URL to use for
+// a given request URL. Changing the contents of cfg will not affect
+// proxy functions created earlier.
+//
+// A nil URL and nil error are returned if no proxy is defined in the
+// environment, or a proxy should not be used for the given request, as
+// defined by NO_PROXY.
+//
+// As a special case, if req.URL.Host is "localhost" (with or without a
+// port number), then a nil URL and nil error will be returned.
+func (cfg *Config) ProxyFunc() func(reqURL *url.URL) (*url.URL, error) {
+	// Preprocess the Config settings for more efficient evaluation.
+	cfg1 := &config{
+		Config: *cfg,
+	}
+	cfg1.init()
+	return cfg1.proxyForURL
+}
+
+func (cfg *config) proxyForURL(reqURL *url.URL) (*url.URL, error) {
+	var proxy *url.URL
+	if reqURL.Scheme == "https" {
+		proxy = cfg.httpsProxy
+	}
+	if proxy == nil {
+		proxy = cfg.httpProxy
+		if proxy != nil && cfg.CGI {
+			return nil, errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")
+		}
+	}
+	if proxy == nil {
+		return nil, nil
+	}
+	if !cfg.useProxy(canonicalAddr(reqURL)) {
+		return nil, nil
+	}
+
+	return proxy, nil
+}
+
+func parseProxy(proxy string) (*url.URL, error) {
+	if proxy == "" {
+		return nil, nil
+	}
+
+	proxyURL, err := url.Parse(proxy)
+	if err != nil ||
+		(proxyURL.Scheme != "http" &&
+			proxyURL.Scheme != "https" &&
+			proxyURL.Scheme != "socks5") {
+		// proxy was bogus. Try prepending "http://" to it and
+		// see if that parses correctly. If not, we fall
+		// through and complain about the original one.
+		if proxyURL, err := url.Parse("http://" + proxy); err == nil {
+			return proxyURL, nil
+		}
+	}
+	if err != nil {
+		return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err)
+	}
+	return proxyURL, nil
+}
+
+// useProxy reports whether requests to addr should use a proxy,
+// according to the NO_PROXY or no_proxy environment variable.
+// addr is always a canonicalAddr with a host and port.
+func (cfg *config) useProxy(addr string) bool {
+	if len(addr) == 0 {
+		return true
+	}
+	host, port, err := net.SplitHostPort(addr)
+	if err != nil {
+		return false
+	}
+	if host == "localhost" {
+		return false
+	}
+	ip := net.ParseIP(host)
+	if ip != nil {
+		if ip.IsLoopback() {
+			return false
+		}
+	}
+
+	addr = strings.ToLower(strings.TrimSpace(host))
+
+	if ip != nil {
+		for _, m := range cfg.ipMatchers {
+			if m.match(addr, port, ip) {
+				return false
+			}
+		}
+	}
+	for _, m := range cfg.domainMatchers {
+		if m.match(addr, port, ip) {
+			return false
+		}
+	}
+	return true
+}
+
+func (c *config) init() {
+	if parsed, err := parseProxy(c.HTTPProxy); err == nil {
+		c.httpProxy = parsed
+	}
+	if parsed, err := parseProxy(c.HTTPSProxy); err == nil {
+		c.httpsProxy = parsed
+	}
+
+	for _, p := range strings.Split(c.NoProxy, ",") {
+		p = strings.ToLower(strings.TrimSpace(p))
+		if len(p) == 0 {
+			continue
+		}
+
+		if p == "*" {
+			c.ipMatchers = []matcher{allMatch{}}
+			c.domainMatchers = []matcher{allMatch{}}
+			return
+		}
+
+		// IPv4/CIDR, IPv6/CIDR
+		if _, pnet, err := net.ParseCIDR(p); err == nil {
+			c.ipMatchers = append(c.ipMatchers, cidrMatch{cidr: pnet})
+			continue
+		}
+
+		// IPv4:port, [IPv6]:port
+		phost, pport, err := net.SplitHostPort(p)
+		if err == nil {
+			if len(phost) == 0 {
+				// There is no host part, likely the entry is malformed; ignore.
+				continue
+			}
+			if phost[0] == '[' && phost[len(phost)-1] == ']' {
+				phost = phost[1 : len(phost)-1]
+			}
+		} else {
+			phost = p
+		}
+		// IPv4, IPv6
+		if pip := net.ParseIP(phost); pip != nil {
+			c.ipMatchers = append(c.ipMatchers, ipMatch{ip: pip, port: pport})
+			continue
+		}
+
+		if len(phost) == 0 {
+			// There is no host part, likely the entry is malformed; ignore.
+			continue
+		}
+
+		// domain.com or domain.com:80
+		// foo.com matches bar.foo.com
+		// .domain.com or .domain.com:port
+		// *.domain.com or *.domain.com:port
+		if strings.HasPrefix(phost, "*.") {
+			phost = phost[1:]
+		}
+		matchHost := false
+		if phost[0] != '.' {
+			matchHost = true
+			phost = "." + phost
+		}
+		c.domainMatchers = append(c.domainMatchers, domainMatch{host: phost, port: pport, matchHost: matchHost})
+	}
+}
+
+var portMap = map[string]string{
+	"http":   "80",
+	"https":  "443",
+	"socks5": "1080",
+}
+
+// canonicalAddr returns url.Host but always with a ":port" suffix
+func canonicalAddr(url *url.URL) string {
+	addr := url.Hostname()
+	if v, err := idnaASCII(addr); err == nil {
+		addr = v
+	}
+	port := url.Port()
+	if port == "" {
+		port = portMap[url.Scheme]
+	}
+	return net.JoinHostPort(addr, port)
+}
+
+// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
+// return true if the string includes a port.
+func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }
+
+func idnaASCII(v string) (string, error) {
+	// TODO: Consider removing this check after verifying performance is okay.
+	// Right now punycode verification, length checks, context checks, and the
+	// permissible character tests are all omitted. It also prevents the ToASCII
+	// call from salvaging an invalid IDN, when possible. As a result it may be
+	// possible to have two IDNs that appear identical to the user where the
+	// ASCII-only version causes an error downstream whereas the non-ASCII
+	// 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) {
+		return v, nil
+	}
+	return idna.Lookup.ToASCII(v)
+}
+
+func isASCII(s string) bool {
+	for i := 0; i < len(s); i++ {
+		if s[i] >= utf8.RuneSelf {
+			return false
+		}
+	}
+	return true
+}
+
+// matcher represents the matching rule for a given value in the NO_PROXY list
+type matcher interface {
+	// match returns true if the host and optional port or ip and optional port
+	// are allowed
+	match(host, port string, ip net.IP) bool
+}
+
+// allMatch matches on all possible inputs
+type allMatch struct{}
+
+func (a allMatch) match(host, port string, ip net.IP) bool {
+	return true
+}
+
+type cidrMatch struct {
+	cidr *net.IPNet
+}
+
+func (m cidrMatch) match(host, port string, ip net.IP) bool {
+	return m.cidr.Contains(ip)
+}
+
+type ipMatch struct {
+	ip   net.IP
+	port string
+}
+
+func (m ipMatch) match(host, port string, ip net.IP) bool {
+	if m.ip.Equal(ip) {
+		return m.port == "" || m.port == port
+	}
+	return false
+}
+
+type domainMatch struct {
+	host string
+	port string
+
+	matchHost bool
+}
+
+func (m domainMatch) match(host, port string, ip net.IP) bool {
+	if strings.HasSuffix(host, m.host) || (m.matchHost && host == m.host[1:]) {
+		return m.port == "" || m.port == port
+	}
+	return false
+}
diff --git a/libgo/go/golang_org/x/net/http/httpproxy/proxy_test.go b/libgo/go/golang_org/x/net/http/httpproxy/proxy_test.go
new file mode 100644
index 00000000000..8791f64bcdc
--- /dev/null
+++ b/libgo/go/golang_org/x/net/http/httpproxy/proxy_test.go
@@ -0,0 +1,351 @@
+// 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 httpproxy_test
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"net/url"
+	"os"
+	"strings"
+	"testing"
+
+	"golang_org/x/net/http/httpproxy"
+)
+
+// setHelper calls t.Helper() for Go 1.9+ (see go19_test.go) and does nothing otherwise.
+var setHelper = func(t *testing.T) {}
+
+type proxyForURLTest struct {
+	cfg     httpproxy.Config
+	req     string // URL to fetch; blank means "http://example.com"
+	want    string
+	wanterr error
+}
+
+func (t proxyForURLTest) String() string {
+	var buf bytes.Buffer
+	space := func() {
+		if buf.Len() > 0 {
+			buf.WriteByte(' ')
+		}
+	}
+	if t.cfg.HTTPProxy != "" {
+		fmt.Fprintf(&buf, "http_proxy=%q", t.cfg.HTTPProxy)
+	}
+	if t.cfg.HTTPSProxy != "" {
+		space()
+		fmt.Fprintf(&buf, "https_proxy=%q", t.cfg.HTTPSProxy)
+	}
+	if t.cfg.NoProxy != "" {
+		space()
+		fmt.Fprintf(&buf, "no_proxy=%q", t.cfg.NoProxy)
+	}
+	req := "http://example.com"
+	if t.req != "" {
+		req = t.req
+	}
+	space()
+	fmt.Fprintf(&buf, "req=%q", req)
+	return strings.TrimSpace(buf.String())
+}
+
+var proxyForURLTests = []proxyForURLTest{{
+	cfg: httpproxy.Config{
+		HTTPProxy: "127.0.0.1:8080",
+	},
+	want: "http://127.0.0.1:8080",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "cache.corp.example.com:1234",
+	},
+	want: "http://cache.corp.example.com:1234",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "cache.corp.example.com",
+	},
+	want: "http://cache.corp.example.com",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "https://cache.corp.example.com",
+	},
+	want: "https://cache.corp.example.com",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "http://127.0.0.1:8080",
+	},
+	want: "http://127.0.0.1:8080",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "https://127.0.0.1:8080",
+	},
+	want: "https://127.0.0.1:8080",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy: "socks5://127.0.0.1",
+	},
+	want: "socks5://127.0.0.1",
+}, {
+	// Don't use secure for http
+	cfg: httpproxy.Config{
+		HTTPProxy:  "http.proxy.tld",
+		HTTPSProxy: "secure.proxy.tld",
+	},
+	req:  "http://insecure.tld/",
+	want: "http://http.proxy.tld",
+}, {
+	// Use secure for https.
+	cfg: httpproxy.Config{
+		HTTPProxy:  "http.proxy.tld",
+		HTTPSProxy: "secure.proxy.tld",
+	},
+	req:  "https://secure.tld/",
+	want: "http://secure.proxy.tld",
+}, {
+	cfg: httpproxy.Config{
+		HTTPProxy:  "http.proxy.tld",
+		HTTPSProxy: "https://secure.proxy.tld",
+	},
+	req:  "https://secure.tld/",
+	want: "https://secure.proxy.tld",
+}, {
+	// Issue 16405: don't use HTTP_PROXY in a CGI environment,
+	// where HTTP_PROXY can be attacker-controlled.
+	cfg: httpproxy.Config{
+		HTTPProxy: "http://10.1.2.3:8080",
+		CGI:       true,
+	},
+	want:    "",
+	wanterr: errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy"),
+}, {
+	// HTTPS proxy is still used even in CGI environment.
+	// (perhaps dubious but it's the historical behaviour).
+	cfg: httpproxy.Config{
+		HTTPSProxy: "https://secure.proxy.tld",
+		CGI:        true,
+	},
+	req:  "https://secure.tld/",
+	want: "https://secure.proxy.tld",
+}, {
+	want: "",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   "example.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   ".example.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "http://proxy",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   "ample.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "http://proxy",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   "example.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://foo.example.com/",
+	want: "",
+}, {
+	cfg: httpproxy.Config{
+		NoProxy:   ".foo.com",
+		HTTPProxy: "proxy",
+	},
+	req:  "http://example.com/",
+	want: "http://proxy",
+}}
+
+func testProxyForURL(t *testing.T, tt proxyForURLTest) {
+	setHelper(t)
+	reqURLStr := tt.req
+	if reqURLStr == "" {
+		reqURLStr = "http://example.com"
+	}
+	reqURL, err := url.Parse(reqURLStr)
+	if err != nil {
+		t.Errorf("invalid URL %q", reqURLStr)
+		return
+	}
+	cfg := tt.cfg
+	proxyForURL := cfg.ProxyFunc()
+	url, err := proxyForURL(reqURL)
+	if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
+		t.Errorf("%v: got error = %q, want %q", tt, g, e)
+		return
+	}
+	if got := fmt.Sprintf("%s", url); got != tt.want {
+		t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want)
+	}
+
+	// Check that changing the Config doesn't change the results
+	// of the functuon.
+	cfg = httpproxy.Config{}
+	url, err = proxyForURL(reqURL)
+	if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
+		t.Errorf("(after mutating config) %v: got error = %q, want %q", tt, g, e)
+		return
+	}
+	if got := fmt.Sprintf("%s", url); got != tt.want {
+		t.Errorf("(after mutating config) %v: got URL = %q, want %q", tt, url, tt.want)
+	}
+}
+
+func TestProxyForURL(t *testing.T) {
+	for _, tt := range proxyForURLTests {
+		testProxyForURL(t, tt)
+	}
+}
+
+func TestFromEnvironment(t *testing.T) {
+	os.Setenv("HTTP_PROXY", "httpproxy")
+	os.Setenv("HTTPS_PROXY", "httpsproxy")
+	os.Setenv("NO_PROXY", "noproxy")
+	os.Setenv("REQUEST_METHOD", "")
+	got := httpproxy.FromEnvironment()
+	want := httpproxy.Config{
+		HTTPProxy:  "httpproxy",
+		HTTPSProxy: "httpsproxy",
+		NoProxy:    "noproxy",
+	}
+	if *got != want {
+		t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+	}
+}
+
+func TestFromEnvironmentWithRequestMethod(t *testing.T) {
+	os.Setenv("HTTP_PROXY", "httpproxy")
+	os.Setenv("HTTPS_PROXY", "httpsproxy")
+	os.Setenv("NO_PROXY", "noproxy")
+	os.Setenv("REQUEST_METHOD", "PUT")
+	got := httpproxy.FromEnvironment()
+	want := httpproxy.Config{
+		HTTPProxy:  "httpproxy",
+		HTTPSProxy: "httpsproxy",
+		NoProxy:    "noproxy",
+		CGI:        true,
+	}
+	if *got != want {
+		t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+	}
+}
+
+func TestFromEnvironmentLowerCase(t *testing.T) {
+	os.Setenv("http_proxy", "httpproxy")
+	os.Setenv("https_proxy", "httpsproxy")
+	os.Setenv("no_proxy", "noproxy")
+	os.Setenv("REQUEST_METHOD", "")
+	got := httpproxy.FromEnvironment()
+	want := httpproxy.Config{
+		HTTPProxy:  "httpproxy",
+		HTTPSProxy: "httpsproxy",
+		NoProxy:    "noproxy",
+	}
+	if *got != want {
+		t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
+	}
+}
+
+var UseProxyTests = []struct {
+	host  string
+	match bool
+}{
+	// Never proxy localhost:
+	{"localhost", false},
+	{"127.0.0.1", false},
+	{"127.0.0.2", false},
+	{"[::1]", false},
+	{"[::2]", true}, // not a loopback address
+
+	{"192.168.1.1", false},                // matches exact IPv4
+	{"192.168.1.2", true},                 // ports do not match
+	{"192.168.1.3", false},                // matches exact IPv4:port
+	{"192.168.1.4", true},                 // no match
+	{"10.0.0.2", false},                   // matches IPv4/CIDR
+	{"[2001:db8::52:0:1]", false},         // matches exact IPv6
+	{"[2001:db8::52:0:2]", true},          // no match
+	{"[2001:db8::52:0:3]", false},         // matches exact [IPv6]:port
+	{"[2002:db8:a::123]", false},          // matches IPv6/CIDR
+	{"[fe80::424b:c8be:1643:a1b6]", true}, // no match
+
+	{"barbaz.net", true},          // does not match as .barbaz.net
+	{"www.barbaz.net", false},     // does match as .barbaz.net
+	{"foobar.com", false},         // does match as foobar.com
+	{"www.foobar.com", false},     // match because NO_PROXY includes "foobar.com"
+	{"foofoobar.com", true},       // not match as a part of foobar.com
+	{"baz.com", true},             // not match as a part of barbaz.com
+	{"localhost.net", true},       // not match as suffix of address
+	{"local.localhost", true},     // not match as prefix as address
+	{"barbarbaz.net", true},       // not match, wrong domain
+	{"wildcard.io", true},         // does not match as *.wildcard.io
+	{"nested.wildcard.io", false}, // match as *.wildcard.io
+	{"awildcard.io", true},        // not a match because of '*'
+}
+
+var noProxy = "foobar.com, .barbaz.net, *.wildcard.io, 192.168.1.1, 192.168.1.2:81, 192.168.1.3:80, 10.0.0.0/30, 2001:db8::52:0:1, [2001:db8::52:0:2]:443, [2001:db8::52:0:3]:80, 2002:db8:a::45/64"
+
+func TestUseProxy(t *testing.T) {
+	cfg := &httpproxy.Config{
+		NoProxy: noProxy,
+	}
+	for _, test := range UseProxyTests {
+		if httpproxy.ExportUseProxy(cfg, test.host+":80") != test.match {
+			t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
+		}
+	}
+}
+
+func TestInvalidNoProxy(t *testing.T) {
+	cfg := &httpproxy.Config{
+		NoProxy: ":1",
+	}
+	ok := httpproxy.ExportUseProxy(cfg, "example.com:80") // should not panic
+	if !ok {
+		t.Errorf("useProxy unexpected return; got false; want true")
+	}
+}
+
+func TestAllNoProxy(t *testing.T) {
+	cfg := &httpproxy.Config{
+		NoProxy: "*",
+	}
+	for _, test := range UseProxyTests {
+		if httpproxy.ExportUseProxy(cfg, test.host+":80") != false {
+			t.Errorf("useProxy(%v) = true, want false", test.host)
+		}
+	}
+}
+
+func BenchmarkProxyForURL(b *testing.B) {
+	cfg := &httpproxy.Config{
+		HTTPProxy:  "http://proxy.example.org",
+		HTTPSProxy: "https://proxy.example.org",
+		NoProxy:    noProxy,
+	}
+	for _, test := range UseProxyTests {
+		u, err := url.Parse("https://" + test.host + ":80")
+		if err != nil {
+			b.Fatalf("parsed failed: %s", test.host)
+		}
+		proxyFunc := cfg.ProxyFunc()
+		b.Run(test.host, func(b *testing.B) {
+			for n := 0; n < b.N; n++ {
+				if au, e := proxyFunc(u); e != nil && test.match == (au != nil) {
+					b.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
+				}
+			}
+		})
+	}
+}
diff --git a/libgo/go/golang_org/x/net/http2/hpack/encode.go b/libgo/go/golang_org/x/net/http2/hpack/encode.go
index 54726c2a3c5..1565cf2702d 100644
--- a/libgo/go/golang_org/x/net/http2/hpack/encode.go
+++ b/libgo/go/golang_org/x/net/http2/hpack/encode.go
@@ -206,7 +206,7 @@ func appendVarInt(dst []byte, n byte, i uint64) []byte {
 }
 
 // appendHpackString appends s, as encoded in "String Literal"
-// representation, to dst and returns the the extended buffer.
+// representation, to dst and returns the extended buffer.
 //
 // s will be encoded in Huffman codes only when it produces strictly
 // shorter byte string.
diff --git a/libgo/go/golang_org/x/net/http2/hpack/hpack.go b/libgo/go/golang_org/x/net/http2/hpack/hpack.go
index 176644acdac..166788ceec5 100644
--- a/libgo/go/golang_org/x/net/http2/hpack/hpack.go
+++ b/libgo/go/golang_org/x/net/http2/hpack/hpack.go
@@ -389,6 +389,12 @@ func (d *Decoder) callEmit(hf HeaderField) error {
 
 // (same invariants and behavior as parseHeaderFieldRepr)
 func (d *Decoder) parseDynamicTableSizeUpdate() error {
+	// RFC 7541, sec 4.2: This dynamic table size update MUST occur at the
+	// beginning of the first header block following the change to the dynamic table size.
+	if d.dynTab.size > 0 {
+		return DecodingError{errors.New("dynamic table size update MUST occur at the beginning of a header block")}
+	}
+
 	buf := d.buf
 	size, buf, err := readVarInt(5, buf)
 	if err != nil {
diff --git a/libgo/go/golang_org/x/net/http2/hpack/hpack_test.go b/libgo/go/golang_org/x/net/http2/hpack/hpack_test.go
index bc7f4767822..3f2227442a9 100644
--- a/libgo/go/golang_org/x/net/http2/hpack/hpack_test.go
+++ b/libgo/go/golang_org/x/net/http2/hpack/hpack_test.go
@@ -462,6 +462,27 @@ func TestHuffmanDecode(t *testing.T) {
 	}
 }
 
+func BenchmarkHuffmanDecode(b *testing.B) {
+	b.StopTimer()
+	enc, err := hex.DecodeString(strings.Replace("94e7 821d d7f2 e6c7 b335 dfdf cd5b 3960 d5af 2708 7f36 72c1 ab27 0fb5 291f 9587 3160 65c0 03ed 4ee5 b106 3d50 07",
+		" ", "", -1))
+	if err != nil {
+		b.Fatal(err)
+	}
+	b.ReportAllocs()
+	b.StartTimer()
+	var buf bytes.Buffer
+	for i := 0; i < b.N; i++ {
+		buf.Reset()
+		if _, err := HuffmanDecode(&buf, enc); err != nil {
+			b.Fatalf("decode error: %v", err)
+		}
+		if string(buf.Bytes()) != "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1" {
+			b.Fatalf("bogus output %q", buf.Bytes())
+		}
+	}
+}
+
 func TestAppendHuffmanString(t *testing.T) {
 	tests := []struct {
 		in, want string
@@ -720,3 +741,22 @@ func TestSaveBufLimit(t *testing.T) {
 		t.Fatalf("Write error = %v; want ErrStringLength", err)
 	}
 }
+
+func TestDynamicSizeUpdate(t *testing.T) {
+	var buf bytes.Buffer
+	enc := NewEncoder(&buf)
+	enc.SetMaxDynamicTableSize(255)
+	enc.WriteField(HeaderField{Name: "foo", Value: "bar"})
+
+	d := NewDecoder(4096, nil)
+	_, err := d.DecodeFull(buf.Bytes())
+	if err != nil {
+		t.Fatalf("unexpected error: got = %v", err)
+	}
+
+	// must fail since the dynamic table update must be at the beginning
+	_, err = d.DecodeFull(buf.Bytes())
+	if err == nil {
+		t.Fatalf("dynamic table size update not at the beginning of a header block")
+	}
+}
diff --git a/libgo/go/golang_org/x/net/http2/hpack/huffman.go b/libgo/go/golang_org/x/net/http2/hpack/huffman.go
index 8850e394677..b412a96c504 100644
--- a/libgo/go/golang_org/x/net/http2/hpack/huffman.go
+++ b/libgo/go/golang_org/x/net/http2/hpack/huffman.go
@@ -47,6 +47,7 @@ var ErrInvalidHuffman = errors.New("hpack: invalid Huffman-encoded data")
 // If maxLen is greater than 0, attempts to write more to buf than
 // maxLen bytes will return ErrStringLength.
 func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
+	rootHuffmanNode := getRootHuffmanNode()
 	n := rootHuffmanNode
 	// cur is the bit buffer that has not been fed into n.
 	// cbits is the number of low order bits in cur that are valid.
@@ -106,7 +107,7 @@ func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
 
 type node struct {
 	// children is non-nil for internal nodes
-	children []*node
+	children *[256]*node
 
 	// The following are only valid if children is nil:
 	codeLen uint8 // number of bits that led to the output of sym
@@ -114,22 +115,31 @@ type node struct {
 }
 
 func newInternalNode() *node {
-	return &node{children: make([]*node, 256)}
+	return &node{children: new([256]*node)}
 }
 
-var rootHuffmanNode = newInternalNode()
+var (
+	buildRootOnce       sync.Once
+	lazyRootHuffmanNode *node
+)
 
-func init() {
+func getRootHuffmanNode() *node {
+	buildRootOnce.Do(buildRootHuffmanNode)
+	return lazyRootHuffmanNode
+}
+
+func buildRootHuffmanNode() {
 	if len(huffmanCodes) != 256 {
 		panic("unexpected size")
 	}
+	lazyRootHuffmanNode = newInternalNode()
 	for i, code := range huffmanCodes {
 		addDecoderNode(byte(i), code, huffmanCodeLen[i])
 	}
 }
 
 func addDecoderNode(sym byte, code uint32, codeLen uint8) {
-	cur := rootHuffmanNode
+	cur := lazyRootHuffmanNode
 	for codeLen > 8 {
 		codeLen -= 8
 		i := uint8(code >> codeLen)
diff --git a/libgo/go/golang_org/x/net/http2/hpack/tables.go b/libgo/go/golang_org/x/net/http2/hpack/tables.go
index 8bd975d388d..a66cfbea69d 100644
--- a/libgo/go/golang_org/x/net/http2/hpack/tables.go
+++ b/libgo/go/golang_org/x/net/http2/hpack/tables.go
@@ -128,67 +128,67 @@ func (t *headerFieldTable) idToIndex(id uint64) uint64 {
 // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
 var staticTable = newStaticTable()
 var staticTableEntries = [...]HeaderField{
-	HeaderField{Name: ":authority"},
-	HeaderField{Name: ":method", Value: "GET"},
-	HeaderField{Name: ":method", Value: "POST"},
-	HeaderField{Name: ":path", Value: "/"},
-	HeaderField{Name: ":path", Value: "/index.html"},
-	HeaderField{Name: ":scheme", Value: "http"},
-	HeaderField{Name: ":scheme", Value: "https"},
-	HeaderField{Name: ":status", Value: "200"},
-	HeaderField{Name: ":status", Value: "204"},
-	HeaderField{Name: ":status", Value: "206"},
-	HeaderField{Name: ":status", Value: "304"},
-	HeaderField{Name: ":status", Value: "400"},
-	HeaderField{Name: ":status", Value: "404"},
-	HeaderField{Name: ":status", Value: "500"},
-	HeaderField{Name: "accept-charset"},
-	HeaderField{Name: "accept-encoding", Value: "gzip, deflate"},
-	HeaderField{Name: "accept-language"},
-	HeaderField{Name: "accept-ranges"},
-	HeaderField{Name: "accept"},
-	HeaderField{Name: "access-control-allow-origin"},
-	HeaderField{Name: "age"},
-	HeaderField{Name: "allow"},
-	HeaderField{Name: "authorization"},
-	HeaderField{Name: "cache-control"},
-	HeaderField{Name: "content-disposition"},
-	HeaderField{Name: "content-encoding"},
-	HeaderField{Name: "content-language"},
-	HeaderField{Name: "content-length"},
-	HeaderField{Name: "content-location"},
-	HeaderField{Name: "content-range"},
-	HeaderField{Name: "content-type"},
-	HeaderField{Name: "cookie"},
-	HeaderField{Name: "date"},
-	HeaderField{Name: "etag"},
-	HeaderField{Name: "expect"},
-	HeaderField{Name: "expires"},
-	HeaderField{Name: "from"},
-	HeaderField{Name: "host"},
-	HeaderField{Name: "if-match"},
-	HeaderField{Name: "if-modified-since"},
-	HeaderField{Name: "if-none-match"},
-	HeaderField{Name: "if-range"},
-	HeaderField{Name: "if-unmodified-since"},
-	HeaderField{Name: "last-modified"},
-	HeaderField{Name: "link"},
-	HeaderField{Name: "location"},
-	HeaderField{Name: "max-forwards"},
-	HeaderField{Name: "proxy-authenticate"},
-	HeaderField{Name: "proxy-authorization"},
-	HeaderField{Name: "range"},
-	HeaderField{Name: "referer"},
-	HeaderField{Name: "refresh"},
-	HeaderField{Name: "retry-after"},
-	HeaderField{Name: "server"},
-	HeaderField{Name: "set-cookie"},
-	HeaderField{Name: "strict-transport-security"},
-	HeaderField{Name: "transfer-encoding"},
-	HeaderField{Name: "user-agent"},
-	HeaderField{Name: "vary"},
-	HeaderField{Name: "via"},
-	HeaderField{Name: "www-authenticate"},
+	{Name: ":authority"},
+	{Name: ":method", Value: "GET"},
+	{Name: ":method", Value: "POST"},
+	{Name: ":path", Value: "/"},
+	{Name: ":path", Value: "/index.html"},
+	{Name: ":scheme", Value: "http"},
+	{Name: ":scheme", Value: "https"},
+	{Name: ":status", Value: "200"},
+	{Name: ":status", Value: "204"},
+	{Name: ":status", Value: "206"},
+	{Name: ":status", Value: "304"},
+	{Name: ":status", Value: "400"},
+	{Name: ":status", Value: "404"},
+	{Name: ":status", Value: "500"},
+	{Name: "accept-charset"},
+	{Name: "accept-encoding", Value: "gzip, deflate"},
+	{Name: "accept-language"},
+	{Name: "accept-ranges"},
+	{Name: "accept"},
+	{Name: "access-control-allow-origin"},
+	{Name: "age"},
+	{Name: "allow"},
+	{Name: "authorization"},
+	{Name: "cache-control"},
+	{Name: "content-disposition"},
+	{Name: "content-encoding"},
+	{Name: "content-language"},
+	{Name: "content-length"},
+	{Name: "content-location"},
+	{Name: "content-range"},
+	{Name: "content-type"},
+	{Name: "cookie"},
+	{Name: "date"},
+	{Name: "etag"},
+	{Name: "expect"},
+	{Name: "expires"},
+	{Name: "from"},
+	{Name: "host"},
+	{Name: "if-match"},
+	{Name: "if-modified-since"},
+	{Name: "if-none-match"},
+	{Name: "if-range"},
+	{Name: "if-unmodified-since"},
+	{Name: "last-modified"},
+	{Name: "link"},
+	{Name: "location"},
+	{Name: "max-forwards"},
+	{Name: "proxy-authenticate"},
+	{Name: "proxy-authorization"},
+	{Name: "range"},
+	{Name: "referer"},
+	{Name: "refresh"},
+	{Name: "retry-after"},
+	{Name: "server"},
+	{Name: "set-cookie"},
+	{Name: "strict-transport-security"},
+	{Name: "transfer-encoding"},
+	{Name: "user-agent"},
+	{Name: "vary"},
+	{Name: "via"},
+	{Name: "www-authenticate"},
 }
 
 func newStaticTable() *headerFieldTable {
diff --git a/libgo/go/golang_org/x/net/internal/nettest/helper_stub.go b/libgo/go/golang_org/x/net/internal/nettest/helper_stub.go
index ea61b6f3992..d729156de67 100644
--- a/libgo/go/golang_org/x/net/internal/nettest/helper_stub.go
+++ b/libgo/go/golang_org/x/net/internal/nettest/helper_stub.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.
 
-// +build nacl plan9
+// +build js,wasm nacl plan9
 
 package nettest
 
diff --git a/libgo/go/golang_org/x/net/internal/nettest/stack.go b/libgo/go/golang_org/x/net/internal/nettest/stack.go
index 06f4e09ef85..46d2fccab58 100644
--- a/libgo/go/golang_org/x/net/internal/nettest/stack.go
+++ b/libgo/go/golang_org/x/net/internal/nettest/stack.go
@@ -64,7 +64,7 @@ func TestableNetwork(network string) bool {
 	switch network {
 	case "unix", "unixgram":
 		switch runtime.GOOS {
-		case "android", "nacl", "plan9", "windows":
+		case "android", "js", "nacl", "plan9", "windows":
 			return false
 		}
 		if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
@@ -72,7 +72,7 @@ func TestableNetwork(network string) bool {
 		}
 	case "unixpacket":
 		switch runtime.GOOS {
-		case "android", "darwin", "freebsd", "nacl", "plan9", "windows":
+		case "android", "darwin", "freebsd", "js", "nacl", "plan9", "windows":
 			return false
 		case "netbsd":
 			// It passes on amd64 at least. 386 fails (Issue 22927). arm is unknown.
diff --git a/libgo/go/hash/crc32/crc32.go b/libgo/go/hash/crc32/crc32.go
index 1912caa212b..908b84adcb2 100644
--- a/libgo/go/hash/crc32/crc32.go
+++ b/libgo/go/hash/crc32/crc32.go
@@ -3,12 +3,12 @@
 // license that can be found in the LICENSE file.
 
 // Package crc32 implements the 32-bit cyclic redundancy check, or CRC-32,
-// checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for
+// checksum. See https://en.wikipedia.org/wiki/Cyclic_redundancy_check for
 // information.
 //
 // Polynomials are represented in LSB-first form also known as reversed representation.
 //
-// See http://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks#Reversed_representations_and_reciprocal_polynomials
+// See https://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks#Reversed_representations_and_reciprocal_polynomials
 // for information.
 package crc32
 
@@ -29,12 +29,12 @@ const (
 
 	// Castagnoli's polynomial, used in iSCSI.
 	// Has better error detection characteristics than IEEE.
-	// http://dx.doi.org/10.1109/26.231911
+	// https://dx.doi.org/10.1109/26.231911
 	Castagnoli = 0x82f63b78
 
 	// Koopman's polynomial.
 	// Also has better error detection characteristics than IEEE.
-	// http://dx.doi.org/10.1109/DSN.2002.1028931
+	// https://dx.doi.org/10.1109/DSN.2002.1028931
 	Koopman = 0xeb31d82e
 )
 
diff --git a/libgo/go/hash/crc64/crc64.go b/libgo/go/hash/crc64/crc64.go
index 3b24c244062..a799a017c93 100644
--- a/libgo/go/hash/crc64/crc64.go
+++ b/libgo/go/hash/crc64/crc64.go
@@ -3,7 +3,7 @@
 // license that can be found in the LICENSE file.
 
 // Package crc64 implements the 64-bit cyclic redundancy check, or CRC-64,
-// checksum. See http://en.wikipedia.org/wiki/Cyclic_redundancy_check for
+// checksum. See https://en.wikipedia.org/wiki/Cyclic_redundancy_check for
 // information.
 package crc64
 
diff --git a/libgo/go/html/entity.go b/libgo/go/html/entity.go
index dfeaf6cabc7..f0f9a6a973c 100644
--- a/libgo/go/html/entity.go
+++ b/libgo/go/html/entity.go
@@ -4,6 +4,8 @@
 
 package html
 
+import "sync"
+
 // All entities that do not end with ';' are 6 or fewer bytes long.
 const longestEntityWithoutSemicolon = 6
 
@@ -13,2241 +15,2251 @@ const longestEntityWithoutSemicolon = 6
 //
 // Note that the HTML5 list is larger than the HTML4 list at
 // http://www.w3.org/TR/html4/sgml/entities.html
-var entity = map[string]rune{
-	"AElig;":                           '\U000000C6',
-	"AMP;":                             '\U00000026',
-	"Aacute;":                          '\U000000C1',
-	"Abreve;":                          '\U00000102',
-	"Acirc;":                           '\U000000C2',
-	"Acy;":                             '\U00000410',
-	"Afr;":                             '\U0001D504',
-	"Agrave;":                          '\U000000C0',
-	"Alpha;":                           '\U00000391',
-	"Amacr;":                           '\U00000100',
-	"And;":                             '\U00002A53',
-	"Aogon;":                           '\U00000104',
-	"Aopf;":                            '\U0001D538',
-	"ApplyFunction;":                   '\U00002061',
-	"Aring;":                           '\U000000C5',
-	"Ascr;":                            '\U0001D49C',
-	"Assign;":                          '\U00002254',
-	"Atilde;":                          '\U000000C3',
-	"Auml;":                            '\U000000C4',
-	"Backslash;":                       '\U00002216',
-	"Barv;":                            '\U00002AE7',
-	"Barwed;":                          '\U00002306',
-	"Bcy;":                             '\U00000411',
-	"Because;":                         '\U00002235',
-	"Bernoullis;":                      '\U0000212C',
-	"Beta;":                            '\U00000392',
-	"Bfr;":                             '\U0001D505',
-	"Bopf;":                            '\U0001D539',
-	"Breve;":                           '\U000002D8',
-	"Bscr;":                            '\U0000212C',
-	"Bumpeq;":                          '\U0000224E',
-	"CHcy;":                            '\U00000427',
-	"COPY;":                            '\U000000A9',
-	"Cacute;":                          '\U00000106',
-	"Cap;":                             '\U000022D2',
-	"CapitalDifferentialD;":            '\U00002145',
-	"Cayleys;":                         '\U0000212D',
-	"Ccaron;":                          '\U0000010C',
-	"Ccedil;":                          '\U000000C7',
-	"Ccirc;":                           '\U00000108',
-	"Cconint;":                         '\U00002230',
-	"Cdot;":                            '\U0000010A',
-	"Cedilla;":                         '\U000000B8',
-	"CenterDot;":                       '\U000000B7',
-	"Cfr;":                             '\U0000212D',
-	"Chi;":                             '\U000003A7',
-	"CircleDot;":                       '\U00002299',
-	"CircleMinus;":                     '\U00002296',
-	"CirclePlus;":                      '\U00002295',
-	"CircleTimes;":                     '\U00002297',
-	"ClockwiseContourIntegral;":        '\U00002232',
-	"CloseCurlyDoubleQuote;":           '\U0000201D',
-	"CloseCurlyQuote;":                 '\U00002019',
-	"Colon;":                           '\U00002237',
-	"Colone;":                          '\U00002A74',
-	"Congruent;":                       '\U00002261',
-	"Conint;":                          '\U0000222F',
-	"ContourIntegral;":                 '\U0000222E',
-	"Copf;":                            '\U00002102',
-	"Coproduct;":                       '\U00002210',
-	"CounterClockwiseContourIntegral;": '\U00002233',
-	"Cross;":                    '\U00002A2F',
-	"Cscr;":                     '\U0001D49E',
-	"Cup;":                      '\U000022D3',
-	"CupCap;":                   '\U0000224D',
-	"DD;":                       '\U00002145',
-	"DDotrahd;":                 '\U00002911',
-	"DJcy;":                     '\U00000402',
-	"DScy;":                     '\U00000405',
-	"DZcy;":                     '\U0000040F',
-	"Dagger;":                   '\U00002021',
-	"Darr;":                     '\U000021A1',
-	"Dashv;":                    '\U00002AE4',
-	"Dcaron;":                   '\U0000010E',
-	"Dcy;":                      '\U00000414',
-	"Del;":                      '\U00002207',
-	"Delta;":                    '\U00000394',
-	"Dfr;":                      '\U0001D507',
-	"DiacriticalAcute;":         '\U000000B4',
-	"DiacriticalDot;":           '\U000002D9',
-	"DiacriticalDoubleAcute;":   '\U000002DD',
-	"DiacriticalGrave;":         '\U00000060',
-	"DiacriticalTilde;":         '\U000002DC',
-	"Diamond;":                  '\U000022C4',
-	"DifferentialD;":            '\U00002146',
-	"Dopf;":                     '\U0001D53B',
-	"Dot;":                      '\U000000A8',
-	"DotDot;":                   '\U000020DC',
-	"DotEqual;":                 '\U00002250',
-	"DoubleContourIntegral;":    '\U0000222F',
-	"DoubleDot;":                '\U000000A8',
-	"DoubleDownArrow;":          '\U000021D3',
-	"DoubleLeftArrow;":          '\U000021D0',
-	"DoubleLeftRightArrow;":     '\U000021D4',
-	"DoubleLeftTee;":            '\U00002AE4',
-	"DoubleLongLeftArrow;":      '\U000027F8',
-	"DoubleLongLeftRightArrow;": '\U000027FA',
-	"DoubleLongRightArrow;":     '\U000027F9',
-	"DoubleRightArrow;":         '\U000021D2',
-	"DoubleRightTee;":           '\U000022A8',
-	"DoubleUpArrow;":            '\U000021D1',
-	"DoubleUpDownArrow;":        '\U000021D5',
-	"DoubleVerticalBar;":        '\U00002225',
-	"DownArrow;":                '\U00002193',
-	"DownArrowBar;":             '\U00002913',
-	"DownArrowUpArrow;":         '\U000021F5',
-	"DownBreve;":                '\U00000311',
-	"DownLeftRightVector;":      '\U00002950',
-	"DownLeftTeeVector;":        '\U0000295E',
-	"DownLeftVector;":           '\U000021BD',
-	"DownLeftVectorBar;":        '\U00002956',
-	"DownRightTeeVector;":       '\U0000295F',
-	"DownRightVector;":          '\U000021C1',
-	"DownRightVectorBar;":       '\U00002957',
-	"DownTee;":                  '\U000022A4',
-	"DownTeeArrow;":             '\U000021A7',
-	"Downarrow;":                '\U000021D3',
-	"Dscr;":                     '\U0001D49F',
-	"Dstrok;":                   '\U00000110',
-	"ENG;":                      '\U0000014A',
-	"ETH;":                      '\U000000D0',
-	"Eacute;":                   '\U000000C9',
-	"Ecaron;":                   '\U0000011A',
-	"Ecirc;":                    '\U000000CA',
-	"Ecy;":                      '\U0000042D',
-	"Edot;":                     '\U00000116',
-	"Efr;":                      '\U0001D508',
-	"Egrave;":                   '\U000000C8',
-	"Element;":                  '\U00002208',
-	"Emacr;":                    '\U00000112',
-	"EmptySmallSquare;":         '\U000025FB',
-	"EmptyVerySmallSquare;":     '\U000025AB',
-	"Eogon;":                    '\U00000118',
-	"Eopf;":                     '\U0001D53C',
-	"Epsilon;":                  '\U00000395',
-	"Equal;":                    '\U00002A75',
-	"EqualTilde;":               '\U00002242',
-	"Equilibrium;":              '\U000021CC',
-	"Escr;":                     '\U00002130',
-	"Esim;":                     '\U00002A73',
-	"Eta;":                      '\U00000397',
-	"Euml;":                     '\U000000CB',
-	"Exists;":                   '\U00002203',
-	"ExponentialE;":             '\U00002147',
-	"Fcy;":                      '\U00000424',
-	"Ffr;":                      '\U0001D509',
-	"FilledSmallSquare;":        '\U000025FC',
-	"FilledVerySmallSquare;":    '\U000025AA',
-	"Fopf;":                     '\U0001D53D',
-	"ForAll;":                   '\U00002200',
-	"Fouriertrf;":               '\U00002131',
-	"Fscr;":                     '\U00002131',
-	"GJcy;":                     '\U00000403',
-	"GT;":                       '\U0000003E',
-	"Gamma;":                    '\U00000393',
-	"Gammad;":                   '\U000003DC',
-	"Gbreve;":                   '\U0000011E',
-	"Gcedil;":                   '\U00000122',
-	"Gcirc;":                    '\U0000011C',
-	"Gcy;":                      '\U00000413',
-	"Gdot;":                     '\U00000120',
-	"Gfr;":                      '\U0001D50A',
-	"Gg;":                       '\U000022D9',
-	"Gopf;":                     '\U0001D53E',
-	"GreaterEqual;":             '\U00002265',
-	"GreaterEqualLess;":         '\U000022DB',
-	"GreaterFullEqual;":         '\U00002267',
-	"GreaterGreater;":           '\U00002AA2',
-	"GreaterLess;":              '\U00002277',
-	"GreaterSlantEqual;":        '\U00002A7E',
-	"GreaterTilde;":             '\U00002273',
-	"Gscr;":                     '\U0001D4A2',
-	"Gt;":                       '\U0000226B',
-	"HARDcy;":                   '\U0000042A',
-	"Hacek;":                    '\U000002C7',
-	"Hat;":                      '\U0000005E',
-	"Hcirc;":                    '\U00000124',
-	"Hfr;":                      '\U0000210C',
-	"HilbertSpace;":             '\U0000210B',
-	"Hopf;":                     '\U0000210D',
-	"HorizontalLine;":           '\U00002500',
-	"Hscr;":                     '\U0000210B',
-	"Hstrok;":                   '\U00000126',
-	"HumpDownHump;":             '\U0000224E',
-	"HumpEqual;":                '\U0000224F',
-	"IEcy;":                     '\U00000415',
-	"IJlig;":                    '\U00000132',
-	"IOcy;":                     '\U00000401',
-	"Iacute;":                   '\U000000CD',
-	"Icirc;":                    '\U000000CE',
-	"Icy;":                      '\U00000418',
-	"Idot;":                     '\U00000130',
-	"Ifr;":                      '\U00002111',
-	"Igrave;":                   '\U000000CC',
-	"Im;":                       '\U00002111',
-	"Imacr;":                    '\U0000012A',
-	"ImaginaryI;":               '\U00002148',
-	"Implies;":                  '\U000021D2',
-	"Int;":                      '\U0000222C',
-	"Integral;":                 '\U0000222B',
-	"Intersection;":             '\U000022C2',
-	"InvisibleComma;":           '\U00002063',
-	"InvisibleTimes;":           '\U00002062',
-	"Iogon;":                    '\U0000012E',
-	"Iopf;":                     '\U0001D540',
-	"Iota;":                     '\U00000399',
-	"Iscr;":                     '\U00002110',
-	"Itilde;":                   '\U00000128',
-	"Iukcy;":                    '\U00000406',
-	"Iuml;":                     '\U000000CF',
-	"Jcirc;":                    '\U00000134',
-	"Jcy;":                      '\U00000419',
-	"Jfr;":                      '\U0001D50D',
-	"Jopf;":                     '\U0001D541',
-	"Jscr;":                     '\U0001D4A5',
-	"Jsercy;":                   '\U00000408',
-	"Jukcy;":                    '\U00000404',
-	"KHcy;":                     '\U00000425',
-	"KJcy;":                     '\U0000040C',
-	"Kappa;":                    '\U0000039A',
-	"Kcedil;":                   '\U00000136',
-	"Kcy;":                      '\U0000041A',
-	"Kfr;":                      '\U0001D50E',
-	"Kopf;":                     '\U0001D542',
-	"Kscr;":                     '\U0001D4A6',
-	"LJcy;":                     '\U00000409',
-	"LT;":                       '\U0000003C',
-	"Lacute;":                   '\U00000139',
-	"Lambda;":                   '\U0000039B',
-	"Lang;":                     '\U000027EA',
-	"Laplacetrf;":               '\U00002112',
-	"Larr;":                     '\U0000219E',
-	"Lcaron;":                   '\U0000013D',
-	"Lcedil;":                   '\U0000013B',
-	"Lcy;":                      '\U0000041B',
-	"LeftAngleBracket;":         '\U000027E8',
-	"LeftArrow;":                '\U00002190',
-	"LeftArrowBar;":             '\U000021E4',
-	"LeftArrowRightArrow;":      '\U000021C6',
-	"LeftCeiling;":              '\U00002308',
-	"LeftDoubleBracket;":        '\U000027E6',
-	"LeftDownTeeVector;":        '\U00002961',
-	"LeftDownVector;":           '\U000021C3',
-	"LeftDownVectorBar;":        '\U00002959',
-	"LeftFloor;":                '\U0000230A',
-	"LeftRightArrow;":           '\U00002194',
-	"LeftRightVector;":          '\U0000294E',
-	"LeftTee;":                  '\U000022A3',
-	"LeftTeeArrow;":             '\U000021A4',
-	"LeftTeeVector;":            '\U0000295A',
-	"LeftTriangle;":             '\U000022B2',
-	"LeftTriangleBar;":          '\U000029CF',
-	"LeftTriangleEqual;":        '\U000022B4',
-	"LeftUpDownVector;":         '\U00002951',
-	"LeftUpTeeVector;":          '\U00002960',
-	"LeftUpVector;":             '\U000021BF',
-	"LeftUpVectorBar;":          '\U00002958',
-	"LeftVector;":               '\U000021BC',
-	"LeftVectorBar;":            '\U00002952',
-	"Leftarrow;":                '\U000021D0',
-	"Leftrightarrow;":           '\U000021D4',
-	"LessEqualGreater;":         '\U000022DA',
-	"LessFullEqual;":            '\U00002266',
-	"LessGreater;":              '\U00002276',
-	"LessLess;":                 '\U00002AA1',
-	"LessSlantEqual;":           '\U00002A7D',
-	"LessTilde;":                '\U00002272',
-	"Lfr;":                      '\U0001D50F',
-	"Ll;":                       '\U000022D8',
-	"Lleftarrow;":               '\U000021DA',
-	"Lmidot;":                   '\U0000013F',
-	"LongLeftArrow;":            '\U000027F5',
-	"LongLeftRightArrow;":       '\U000027F7',
-	"LongRightArrow;":           '\U000027F6',
-	"Longleftarrow;":            '\U000027F8',
-	"Longleftrightarrow;":       '\U000027FA',
-	"Longrightarrow;":           '\U000027F9',
-	"Lopf;":                     '\U0001D543',
-	"LowerLeftArrow;":           '\U00002199',
-	"LowerRightArrow;":          '\U00002198',
-	"Lscr;":                     '\U00002112',
-	"Lsh;":                      '\U000021B0',
-	"Lstrok;":                   '\U00000141',
-	"Lt;":                       '\U0000226A',
-	"Map;":                      '\U00002905',
-	"Mcy;":                      '\U0000041C',
-	"MediumSpace;":              '\U0000205F',
-	"Mellintrf;":                '\U00002133',
-	"Mfr;":                      '\U0001D510',
-	"MinusPlus;":                '\U00002213',
-	"Mopf;":                     '\U0001D544',
-	"Mscr;":                     '\U00002133',
-	"Mu;":                       '\U0000039C',
-	"NJcy;":                     '\U0000040A',
-	"Nacute;":                   '\U00000143',
-	"Ncaron;":                   '\U00000147',
-	"Ncedil;":                   '\U00000145',
-	"Ncy;":                      '\U0000041D',
-	"NegativeMediumSpace;":      '\U0000200B',
-	"NegativeThickSpace;":       '\U0000200B',
-	"NegativeThinSpace;":        '\U0000200B',
-	"NegativeVeryThinSpace;":    '\U0000200B',
-	"NestedGreaterGreater;":     '\U0000226B',
-	"NestedLessLess;":           '\U0000226A',
-	"NewLine;":                  '\U0000000A',
-	"Nfr;":                      '\U0001D511',
-	"NoBreak;":                  '\U00002060',
-	"NonBreakingSpace;":         '\U000000A0',
-	"Nopf;":                     '\U00002115',
-	"Not;":                      '\U00002AEC',
-	"NotCongruent;":             '\U00002262',
-	"NotCupCap;":                '\U0000226D',
-	"NotDoubleVerticalBar;":     '\U00002226',
-	"NotElement;":               '\U00002209',
-	"NotEqual;":                 '\U00002260',
-	"NotExists;":                '\U00002204',
-	"NotGreater;":               '\U0000226F',
-	"NotGreaterEqual;":          '\U00002271',
-	"NotGreaterLess;":           '\U00002279',
-	"NotGreaterTilde;":          '\U00002275',
-	"NotLeftTriangle;":          '\U000022EA',
-	"NotLeftTriangleEqual;":     '\U000022EC',
-	"NotLess;":                  '\U0000226E',
-	"NotLessEqual;":             '\U00002270',
-	"NotLessGreater;":           '\U00002278',
-	"NotLessTilde;":             '\U00002274',
-	"NotPrecedes;":              '\U00002280',
-	"NotPrecedesSlantEqual;":    '\U000022E0',
-	"NotReverseElement;":        '\U0000220C',
-	"NotRightTriangle;":         '\U000022EB',
-	"NotRightTriangleEqual;":    '\U000022ED',
-	"NotSquareSubsetEqual;":     '\U000022E2',
-	"NotSquareSupersetEqual;":   '\U000022E3',
-	"NotSubsetEqual;":           '\U00002288',
-	"NotSucceeds;":              '\U00002281',
-	"NotSucceedsSlantEqual;":    '\U000022E1',
-	"NotSupersetEqual;":         '\U00002289',
-	"NotTilde;":                 '\U00002241',
-	"NotTildeEqual;":            '\U00002244',
-	"NotTildeFullEqual;":        '\U00002247',
-	"NotTildeTilde;":            '\U00002249',
-	"NotVerticalBar;":           '\U00002224',
-	"Nscr;":                     '\U0001D4A9',
-	"Ntilde;":                   '\U000000D1',
-	"Nu;":                       '\U0000039D',
-	"OElig;":                    '\U00000152',
-	"Oacute;":                   '\U000000D3',
-	"Ocirc;":                    '\U000000D4',
-	"Ocy;":                      '\U0000041E',
-	"Odblac;":                   '\U00000150',
-	"Ofr;":                      '\U0001D512',
-	"Ograve;":                   '\U000000D2',
-	"Omacr;":                    '\U0000014C',
-	"Omega;":                    '\U000003A9',
-	"Omicron;":                  '\U0000039F',
-	"Oopf;":                     '\U0001D546',
-	"OpenCurlyDoubleQuote;":     '\U0000201C',
-	"OpenCurlyQuote;":           '\U00002018',
-	"Or;":                       '\U00002A54',
-	"Oscr;":                     '\U0001D4AA',
-	"Oslash;":                   '\U000000D8',
-	"Otilde;":                   '\U000000D5',
-	"Otimes;":                   '\U00002A37',
-	"Ouml;":                     '\U000000D6',
-	"OverBar;":                  '\U0000203E',
-	"OverBrace;":                '\U000023DE',
-	"OverBracket;":              '\U000023B4',
-	"OverParenthesis;":          '\U000023DC',
-	"PartialD;":                 '\U00002202',
-	"Pcy;":                      '\U0000041F',
-	"Pfr;":                      '\U0001D513',
-	"Phi;":                      '\U000003A6',
-	"Pi;":                       '\U000003A0',
-	"PlusMinus;":                '\U000000B1',
-	"Poincareplane;":            '\U0000210C',
-	"Popf;":                     '\U00002119',
-	"Pr;":                       '\U00002ABB',
-	"Precedes;":                 '\U0000227A',
-	"PrecedesEqual;":            '\U00002AAF',
-	"PrecedesSlantEqual;":       '\U0000227C',
-	"PrecedesTilde;":            '\U0000227E',
-	"Prime;":                    '\U00002033',
-	"Product;":                  '\U0000220F',
-	"Proportion;":               '\U00002237',
-	"Proportional;":             '\U0000221D',
-	"Pscr;":                     '\U0001D4AB',
-	"Psi;":                      '\U000003A8',
-	"QUOT;":                     '\U00000022',
-	"Qfr;":                      '\U0001D514',
-	"Qopf;":                     '\U0000211A',
-	"Qscr;":                     '\U0001D4AC',
-	"RBarr;":                    '\U00002910',
-	"REG;":                      '\U000000AE',
-	"Racute;":                   '\U00000154',
-	"Rang;":                     '\U000027EB',
-	"Rarr;":                     '\U000021A0',
-	"Rarrtl;":                   '\U00002916',
-	"Rcaron;":                   '\U00000158',
-	"Rcedil;":                   '\U00000156',
-	"Rcy;":                      '\U00000420',
-	"Re;":                       '\U0000211C',
-	"ReverseElement;":           '\U0000220B',
-	"ReverseEquilibrium;":       '\U000021CB',
-	"ReverseUpEquilibrium;":     '\U0000296F',
-	"Rfr;":                      '\U0000211C',
-	"Rho;":                      '\U000003A1',
-	"RightAngleBracket;":        '\U000027E9',
-	"RightArrow;":               '\U00002192',
-	"RightArrowBar;":            '\U000021E5',
-	"RightArrowLeftArrow;":      '\U000021C4',
-	"RightCeiling;":             '\U00002309',
-	"RightDoubleBracket;":       '\U000027E7',
-	"RightDownTeeVector;":       '\U0000295D',
-	"RightDownVector;":          '\U000021C2',
-	"RightDownVectorBar;":       '\U00002955',
-	"RightFloor;":               '\U0000230B',
-	"RightTee;":                 '\U000022A2',
-	"RightTeeArrow;":            '\U000021A6',
-	"RightTeeVector;":           '\U0000295B',
-	"RightTriangle;":            '\U000022B3',
-	"RightTriangleBar;":         '\U000029D0',
-	"RightTriangleEqual;":       '\U000022B5',
-	"RightUpDownVector;":        '\U0000294F',
-	"RightUpTeeVector;":         '\U0000295C',
-	"RightUpVector;":            '\U000021BE',
-	"RightUpVectorBar;":         '\U00002954',
-	"RightVector;":              '\U000021C0',
-	"RightVectorBar;":           '\U00002953',
-	"Rightarrow;":               '\U000021D2',
-	"Ropf;":                     '\U0000211D',
-	"RoundImplies;":             '\U00002970',
-	"Rrightarrow;":              '\U000021DB',
-	"Rscr;":                     '\U0000211B',
-	"Rsh;":                      '\U000021B1',
-	"RuleDelayed;":              '\U000029F4',
-	"SHCHcy;":                   '\U00000429',
-	"SHcy;":                     '\U00000428',
-	"SOFTcy;":                   '\U0000042C',
-	"Sacute;":                   '\U0000015A',
-	"Sc;":                       '\U00002ABC',
-	"Scaron;":                   '\U00000160',
-	"Scedil;":                   '\U0000015E',
-	"Scirc;":                    '\U0000015C',
-	"Scy;":                      '\U00000421',
-	"Sfr;":                      '\U0001D516',
-	"ShortDownArrow;":           '\U00002193',
-	"ShortLeftArrow;":           '\U00002190',
-	"ShortRightArrow;":          '\U00002192',
-	"ShortUpArrow;":             '\U00002191',
-	"Sigma;":                    '\U000003A3',
-	"SmallCircle;":              '\U00002218',
-	"Sopf;":                     '\U0001D54A',
-	"Sqrt;":                     '\U0000221A',
-	"Square;":                   '\U000025A1',
-	"SquareIntersection;":       '\U00002293',
-	"SquareSubset;":             '\U0000228F',
-	"SquareSubsetEqual;":        '\U00002291',
-	"SquareSuperset;":           '\U00002290',
-	"SquareSupersetEqual;":      '\U00002292',
-	"SquareUnion;":              '\U00002294',
-	"Sscr;":                     '\U0001D4AE',
-	"Star;":                     '\U000022C6',
-	"Sub;":                      '\U000022D0',
-	"Subset;":                   '\U000022D0',
-	"SubsetEqual;":              '\U00002286',
-	"Succeeds;":                 '\U0000227B',
-	"SucceedsEqual;":            '\U00002AB0',
-	"SucceedsSlantEqual;":       '\U0000227D',
-	"SucceedsTilde;":            '\U0000227F',
-	"SuchThat;":                 '\U0000220B',
-	"Sum;":                      '\U00002211',
-	"Sup;":                      '\U000022D1',
-	"Superset;":                 '\U00002283',
-	"SupersetEqual;":            '\U00002287',
-	"Supset;":                   '\U000022D1',
-	"THORN;":                    '\U000000DE',
-	"TRADE;":                    '\U00002122',
-	"TSHcy;":                    '\U0000040B',
-	"TScy;":                     '\U00000426',
-	"Tab;":                      '\U00000009',
-	"Tau;":                      '\U000003A4',
-	"Tcaron;":                   '\U00000164',
-	"Tcedil;":                   '\U00000162',
-	"Tcy;":                      '\U00000422',
-	"Tfr;":                      '\U0001D517',
-	"Therefore;":                '\U00002234',
-	"Theta;":                    '\U00000398',
-	"ThinSpace;":                '\U00002009',
-	"Tilde;":                    '\U0000223C',
-	"TildeEqual;":               '\U00002243',
-	"TildeFullEqual;":           '\U00002245',
-	"TildeTilde;":               '\U00002248',
-	"Topf;":                     '\U0001D54B',
-	"TripleDot;":                '\U000020DB',
-	"Tscr;":                     '\U0001D4AF',
-	"Tstrok;":                   '\U00000166',
-	"Uacute;":                   '\U000000DA',
-	"Uarr;":                     '\U0000219F',
-	"Uarrocir;":                 '\U00002949',
-	"Ubrcy;":                    '\U0000040E',
-	"Ubreve;":                   '\U0000016C',
-	"Ucirc;":                    '\U000000DB',
-	"Ucy;":                      '\U00000423',
-	"Udblac;":                   '\U00000170',
-	"Ufr;":                      '\U0001D518',
-	"Ugrave;":                   '\U000000D9',
-	"Umacr;":                    '\U0000016A',
-	"UnderBar;":                 '\U0000005F',
-	"UnderBrace;":               '\U000023DF',
-	"UnderBracket;":             '\U000023B5',
-	"UnderParenthesis;":         '\U000023DD',
-	"Union;":                    '\U000022C3',
-	"UnionPlus;":                '\U0000228E',
-	"Uogon;":                    '\U00000172',
-	"Uopf;":                     '\U0001D54C',
-	"UpArrow;":                  '\U00002191',
-	"UpArrowBar;":               '\U00002912',
-	"UpArrowDownArrow;":         '\U000021C5',
-	"UpDownArrow;":              '\U00002195',
-	"UpEquilibrium;":            '\U0000296E',
-	"UpTee;":                    '\U000022A5',
-	"UpTeeArrow;":               '\U000021A5',
-	"Uparrow;":                  '\U000021D1',
-	"Updownarrow;":              '\U000021D5',
-	"UpperLeftArrow;":           '\U00002196',
-	"UpperRightArrow;":          '\U00002197',
-	"Upsi;":                     '\U000003D2',
-	"Upsilon;":                  '\U000003A5',
-	"Uring;":                    '\U0000016E',
-	"Uscr;":                     '\U0001D4B0',
-	"Utilde;":                   '\U00000168',
-	"Uuml;":                     '\U000000DC',
-	"VDash;":                    '\U000022AB',
-	"Vbar;":                     '\U00002AEB',
-	"Vcy;":                      '\U00000412',
-	"Vdash;":                    '\U000022A9',
-	"Vdashl;":                   '\U00002AE6',
-	"Vee;":                      '\U000022C1',
-	"Verbar;":                   '\U00002016',
-	"Vert;":                     '\U00002016',
-	"VerticalBar;":              '\U00002223',
-	"VerticalLine;":             '\U0000007C',
-	"VerticalSeparator;":        '\U00002758',
-	"VerticalTilde;":            '\U00002240',
-	"VeryThinSpace;":            '\U0000200A',
-	"Vfr;":                      '\U0001D519',
-	"Vopf;":                     '\U0001D54D',
-	"Vscr;":                     '\U0001D4B1',
-	"Vvdash;":                   '\U000022AA',
-	"Wcirc;":                    '\U00000174',
-	"Wedge;":                    '\U000022C0',
-	"Wfr;":                      '\U0001D51A',
-	"Wopf;":                     '\U0001D54E',
-	"Wscr;":                     '\U0001D4B2',
-	"Xfr;":                      '\U0001D51B',
-	"Xi;":                       '\U0000039E',
-	"Xopf;":                     '\U0001D54F',
-	"Xscr;":                     '\U0001D4B3',
-	"YAcy;":                     '\U0000042F',
-	"YIcy;":                     '\U00000407',
-	"YUcy;":                     '\U0000042E',
-	"Yacute;":                   '\U000000DD',
-	"Ycirc;":                    '\U00000176',
-	"Ycy;":                      '\U0000042B',
-	"Yfr;":                      '\U0001D51C',
-	"Yopf;":                     '\U0001D550',
-	"Yscr;":                     '\U0001D4B4',
-	"Yuml;":                     '\U00000178',
-	"ZHcy;":                     '\U00000416',
-	"Zacute;":                   '\U00000179',
-	"Zcaron;":                   '\U0000017D',
-	"Zcy;":                      '\U00000417',
-	"Zdot;":                     '\U0000017B',
-	"ZeroWidthSpace;":           '\U0000200B',
-	"Zeta;":                     '\U00000396',
-	"Zfr;":                      '\U00002128',
-	"Zopf;":                     '\U00002124',
-	"Zscr;":                     '\U0001D4B5',
-	"aacute;":                   '\U000000E1',
-	"abreve;":                   '\U00000103',
-	"ac;":                       '\U0000223E',
-	"acd;":                      '\U0000223F',
-	"acirc;":                    '\U000000E2',
-	"acute;":                    '\U000000B4',
-	"acy;":                      '\U00000430',
-	"aelig;":                    '\U000000E6',
-	"af;":                       '\U00002061',
-	"afr;":                      '\U0001D51E',
-	"agrave;":                   '\U000000E0',
-	"alefsym;":                  '\U00002135',
-	"aleph;":                    '\U00002135',
-	"alpha;":                    '\U000003B1',
-	"amacr;":                    '\U00000101',
-	"amalg;":                    '\U00002A3F',
-	"amp;":                      '\U00000026',
-	"and;":                      '\U00002227',
-	"andand;":                   '\U00002A55',
-	"andd;":                     '\U00002A5C',
-	"andslope;":                 '\U00002A58',
-	"andv;":                     '\U00002A5A',
-	"ang;":                      '\U00002220',
-	"ange;":                     '\U000029A4',
-	"angle;":                    '\U00002220',
-	"angmsd;":                   '\U00002221',
-	"angmsdaa;":                 '\U000029A8',
-	"angmsdab;":                 '\U000029A9',
-	"angmsdac;":                 '\U000029AA',
-	"angmsdad;":                 '\U000029AB',
-	"angmsdae;":                 '\U000029AC',
-	"angmsdaf;":                 '\U000029AD',
-	"angmsdag;":                 '\U000029AE',
-	"angmsdah;":                 '\U000029AF',
-	"angrt;":                    '\U0000221F',
-	"angrtvb;":                  '\U000022BE',
-	"angrtvbd;":                 '\U0000299D',
-	"angsph;":                   '\U00002222',
-	"angst;":                    '\U000000C5',
-	"angzarr;":                  '\U0000237C',
-	"aogon;":                    '\U00000105',
-	"aopf;":                     '\U0001D552',
-	"ap;":                       '\U00002248',
-	"apE;":                      '\U00002A70',
-	"apacir;":                   '\U00002A6F',
-	"ape;":                      '\U0000224A',
-	"apid;":                     '\U0000224B',
-	"apos;":                     '\U00000027',
-	"approx;":                   '\U00002248',
-	"approxeq;":                 '\U0000224A',
-	"aring;":                    '\U000000E5',
-	"ascr;":                     '\U0001D4B6',
-	"ast;":                      '\U0000002A',
-	"asymp;":                    '\U00002248',
-	"asympeq;":                  '\U0000224D',
-	"atilde;":                   '\U000000E3',
-	"auml;":                     '\U000000E4',
-	"awconint;":                 '\U00002233',
-	"awint;":                    '\U00002A11',
-	"bNot;":                     '\U00002AED',
-	"backcong;":                 '\U0000224C',
-	"backepsilon;":              '\U000003F6',
-	"backprime;":                '\U00002035',
-	"backsim;":                  '\U0000223D',
-	"backsimeq;":                '\U000022CD',
-	"barvee;":                   '\U000022BD',
-	"barwed;":                   '\U00002305',
-	"barwedge;":                 '\U00002305',
-	"bbrk;":                     '\U000023B5',
-	"bbrktbrk;":                 '\U000023B6',
-	"bcong;":                    '\U0000224C',
-	"bcy;":                      '\U00000431',
-	"bdquo;":                    '\U0000201E',
-	"becaus;":                   '\U00002235',
-	"because;":                  '\U00002235',
-	"bemptyv;":                  '\U000029B0',
-	"bepsi;":                    '\U000003F6',
-	"bernou;":                   '\U0000212C',
-	"beta;":                     '\U000003B2',
-	"beth;":                     '\U00002136',
-	"between;":                  '\U0000226C',
-	"bfr;":                      '\U0001D51F',
-	"bigcap;":                   '\U000022C2',
-	"bigcirc;":                  '\U000025EF',
-	"bigcup;":                   '\U000022C3',
-	"bigodot;":                  '\U00002A00',
-	"bigoplus;":                 '\U00002A01',
-	"bigotimes;":                '\U00002A02',
-	"bigsqcup;":                 '\U00002A06',
-	"bigstar;":                  '\U00002605',
-	"bigtriangledown;":          '\U000025BD',
-	"bigtriangleup;":            '\U000025B3',
-	"biguplus;":                 '\U00002A04',
-	"bigvee;":                   '\U000022C1',
-	"bigwedge;":                 '\U000022C0',
-	"bkarow;":                   '\U0000290D',
-	"blacklozenge;":             '\U000029EB',
-	"blacksquare;":              '\U000025AA',
-	"blacktriangle;":            '\U000025B4',
-	"blacktriangledown;":        '\U000025BE',
-	"blacktriangleleft;":        '\U000025C2',
-	"blacktriangleright;":       '\U000025B8',
-	"blank;":                    '\U00002423',
-	"blk12;":                    '\U00002592',
-	"blk14;":                    '\U00002591',
-	"blk34;":                    '\U00002593',
-	"block;":                    '\U00002588',
-	"bnot;":                     '\U00002310',
-	"bopf;":                     '\U0001D553',
-	"bot;":                      '\U000022A5',
-	"bottom;":                   '\U000022A5',
-	"bowtie;":                   '\U000022C8',
-	"boxDL;":                    '\U00002557',
-	"boxDR;":                    '\U00002554',
-	"boxDl;":                    '\U00002556',
-	"boxDr;":                    '\U00002553',
-	"boxH;":                     '\U00002550',
-	"boxHD;":                    '\U00002566',
-	"boxHU;":                    '\U00002569',
-	"boxHd;":                    '\U00002564',
-	"boxHu;":                    '\U00002567',
-	"boxUL;":                    '\U0000255D',
-	"boxUR;":                    '\U0000255A',
-	"boxUl;":                    '\U0000255C',
-	"boxUr;":                    '\U00002559',
-	"boxV;":                     '\U00002551',
-	"boxVH;":                    '\U0000256C',
-	"boxVL;":                    '\U00002563',
-	"boxVR;":                    '\U00002560',
-	"boxVh;":                    '\U0000256B',
-	"boxVl;":                    '\U00002562',
-	"boxVr;":                    '\U0000255F',
-	"boxbox;":                   '\U000029C9',
-	"boxdL;":                    '\U00002555',
-	"boxdR;":                    '\U00002552',
-	"boxdl;":                    '\U00002510',
-	"boxdr;":                    '\U0000250C',
-	"boxh;":                     '\U00002500',
-	"boxhD;":                    '\U00002565',
-	"boxhU;":                    '\U00002568',
-	"boxhd;":                    '\U0000252C',
-	"boxhu;":                    '\U00002534',
-	"boxminus;":                 '\U0000229F',
-	"boxplus;":                  '\U0000229E',
-	"boxtimes;":                 '\U000022A0',
-	"boxuL;":                    '\U0000255B',
-	"boxuR;":                    '\U00002558',
-	"boxul;":                    '\U00002518',
-	"boxur;":                    '\U00002514',
-	"boxv;":                     '\U00002502',
-	"boxvH;":                    '\U0000256A',
-	"boxvL;":                    '\U00002561',
-	"boxvR;":                    '\U0000255E',
-	"boxvh;":                    '\U0000253C',
-	"boxvl;":                    '\U00002524',
-	"boxvr;":                    '\U0000251C',
-	"bprime;":                   '\U00002035',
-	"breve;":                    '\U000002D8',
-	"brvbar;":                   '\U000000A6',
-	"bscr;":                     '\U0001D4B7',
-	"bsemi;":                    '\U0000204F',
-	"bsim;":                     '\U0000223D',
-	"bsime;":                    '\U000022CD',
-	"bsol;":                     '\U0000005C',
-	"bsolb;":                    '\U000029C5',
-	"bsolhsub;":                 '\U000027C8',
-	"bull;":                     '\U00002022',
-	"bullet;":                   '\U00002022',
-	"bump;":                     '\U0000224E',
-	"bumpE;":                    '\U00002AAE',
-	"bumpe;":                    '\U0000224F',
-	"bumpeq;":                   '\U0000224F',
-	"cacute;":                   '\U00000107',
-	"cap;":                      '\U00002229',
-	"capand;":                   '\U00002A44',
-	"capbrcup;":                 '\U00002A49',
-	"capcap;":                   '\U00002A4B',
-	"capcup;":                   '\U00002A47',
-	"capdot;":                   '\U00002A40',
-	"caret;":                    '\U00002041',
-	"caron;":                    '\U000002C7',
-	"ccaps;":                    '\U00002A4D',
-	"ccaron;":                   '\U0000010D',
-	"ccedil;":                   '\U000000E7',
-	"ccirc;":                    '\U00000109',
-	"ccups;":                    '\U00002A4C',
-	"ccupssm;":                  '\U00002A50',
-	"cdot;":                     '\U0000010B',
-	"cedil;":                    '\U000000B8',
-	"cemptyv;":                  '\U000029B2',
-	"cent;":                     '\U000000A2',
-	"centerdot;":                '\U000000B7',
-	"cfr;":                      '\U0001D520',
-	"chcy;":                     '\U00000447',
-	"check;":                    '\U00002713',
-	"checkmark;":                '\U00002713',
-	"chi;":                      '\U000003C7',
-	"cir;":                      '\U000025CB',
-	"cirE;":                     '\U000029C3',
-	"circ;":                     '\U000002C6',
-	"circeq;":                   '\U00002257',
-	"circlearrowleft;":          '\U000021BA',
-	"circlearrowright;":         '\U000021BB',
-	"circledR;":                 '\U000000AE',
-	"circledS;":                 '\U000024C8',
-	"circledast;":               '\U0000229B',
-	"circledcirc;":              '\U0000229A',
-	"circleddash;":              '\U0000229D',
-	"cire;":                     '\U00002257',
-	"cirfnint;":                 '\U00002A10',
-	"cirmid;":                   '\U00002AEF',
-	"cirscir;":                  '\U000029C2',
-	"clubs;":                    '\U00002663',
-	"clubsuit;":                 '\U00002663',
-	"colon;":                    '\U0000003A',
-	"colone;":                   '\U00002254',
-	"coloneq;":                  '\U00002254',
-	"comma;":                    '\U0000002C',
-	"commat;":                   '\U00000040',
-	"comp;":                     '\U00002201',
-	"compfn;":                   '\U00002218',
-	"complement;":               '\U00002201',
-	"complexes;":                '\U00002102',
-	"cong;":                     '\U00002245',
-	"congdot;":                  '\U00002A6D',
-	"conint;":                   '\U0000222E',
-	"copf;":                     '\U0001D554',
-	"coprod;":                   '\U00002210',
-	"copy;":                     '\U000000A9',
-	"copysr;":                   '\U00002117',
-	"crarr;":                    '\U000021B5',
-	"cross;":                    '\U00002717',
-	"cscr;":                     '\U0001D4B8',
-	"csub;":                     '\U00002ACF',
-	"csube;":                    '\U00002AD1',
-	"csup;":                     '\U00002AD0',
-	"csupe;":                    '\U00002AD2',
-	"ctdot;":                    '\U000022EF',
-	"cudarrl;":                  '\U00002938',
-	"cudarrr;":                  '\U00002935',
-	"cuepr;":                    '\U000022DE',
-	"cuesc;":                    '\U000022DF',
-	"cularr;":                   '\U000021B6',
-	"cularrp;":                  '\U0000293D',
-	"cup;":                      '\U0000222A',
-	"cupbrcap;":                 '\U00002A48',
-	"cupcap;":                   '\U00002A46',
-	"cupcup;":                   '\U00002A4A',
-	"cupdot;":                   '\U0000228D',
-	"cupor;":                    '\U00002A45',
-	"curarr;":                   '\U000021B7',
-	"curarrm;":                  '\U0000293C',
-	"curlyeqprec;":              '\U000022DE',
-	"curlyeqsucc;":              '\U000022DF',
-	"curlyvee;":                 '\U000022CE',
-	"curlywedge;":               '\U000022CF',
-	"curren;":                   '\U000000A4',
-	"curvearrowleft;":           '\U000021B6',
-	"curvearrowright;":          '\U000021B7',
-	"cuvee;":                    '\U000022CE',
-	"cuwed;":                    '\U000022CF',
-	"cwconint;":                 '\U00002232',
-	"cwint;":                    '\U00002231',
-	"cylcty;":                   '\U0000232D',
-	"dArr;":                     '\U000021D3',
-	"dHar;":                     '\U00002965',
-	"dagger;":                   '\U00002020',
-	"daleth;":                   '\U00002138',
-	"darr;":                     '\U00002193',
-	"dash;":                     '\U00002010',
-	"dashv;":                    '\U000022A3',
-	"dbkarow;":                  '\U0000290F',
-	"dblac;":                    '\U000002DD',
-	"dcaron;":                   '\U0000010F',
-	"dcy;":                      '\U00000434',
-	"dd;":                       '\U00002146',
-	"ddagger;":                  '\U00002021',
-	"ddarr;":                    '\U000021CA',
-	"ddotseq;":                  '\U00002A77',
-	"deg;":                      '\U000000B0',
-	"delta;":                    '\U000003B4',
-	"demptyv;":                  '\U000029B1',
-	"dfisht;":                   '\U0000297F',
-	"dfr;":                      '\U0001D521',
-	"dharl;":                    '\U000021C3',
-	"dharr;":                    '\U000021C2',
-	"diam;":                     '\U000022C4',
-	"diamond;":                  '\U000022C4',
-	"diamondsuit;":              '\U00002666',
-	"diams;":                    '\U00002666',
-	"die;":                      '\U000000A8',
-	"digamma;":                  '\U000003DD',
-	"disin;":                    '\U000022F2',
-	"div;":                      '\U000000F7',
-	"divide;":                   '\U000000F7',
-	"divideontimes;":            '\U000022C7',
-	"divonx;":                   '\U000022C7',
-	"djcy;":                     '\U00000452',
-	"dlcorn;":                   '\U0000231E',
-	"dlcrop;":                   '\U0000230D',
-	"dollar;":                   '\U00000024',
-	"dopf;":                     '\U0001D555',
-	"dot;":                      '\U000002D9',
-	"doteq;":                    '\U00002250',
-	"doteqdot;":                 '\U00002251',
-	"dotminus;":                 '\U00002238',
-	"dotplus;":                  '\U00002214',
-	"dotsquare;":                '\U000022A1',
-	"doublebarwedge;":           '\U00002306',
-	"downarrow;":                '\U00002193',
-	"downdownarrows;":           '\U000021CA',
-	"downharpoonleft;":          '\U000021C3',
-	"downharpoonright;":         '\U000021C2',
-	"drbkarow;":                 '\U00002910',
-	"drcorn;":                   '\U0000231F',
-	"drcrop;":                   '\U0000230C',
-	"dscr;":                     '\U0001D4B9',
-	"dscy;":                     '\U00000455',
-	"dsol;":                     '\U000029F6',
-	"dstrok;":                   '\U00000111',
-	"dtdot;":                    '\U000022F1',
-	"dtri;":                     '\U000025BF',
-	"dtrif;":                    '\U000025BE',
-	"duarr;":                    '\U000021F5',
-	"duhar;":                    '\U0000296F',
-	"dwangle;":                  '\U000029A6',
-	"dzcy;":                     '\U0000045F',
-	"dzigrarr;":                 '\U000027FF',
-	"eDDot;":                    '\U00002A77',
-	"eDot;":                     '\U00002251',
-	"eacute;":                   '\U000000E9',
-	"easter;":                   '\U00002A6E',
-	"ecaron;":                   '\U0000011B',
-	"ecir;":                     '\U00002256',
-	"ecirc;":                    '\U000000EA',
-	"ecolon;":                   '\U00002255',
-	"ecy;":                      '\U0000044D',
-	"edot;":                     '\U00000117',
-	"ee;":                       '\U00002147',
-	"efDot;":                    '\U00002252',
-	"efr;":                      '\U0001D522',
-	"eg;":                       '\U00002A9A',
-	"egrave;":                   '\U000000E8',
-	"egs;":                      '\U00002A96',
-	"egsdot;":                   '\U00002A98',
-	"el;":                       '\U00002A99',
-	"elinters;":                 '\U000023E7',
-	"ell;":                      '\U00002113',
-	"els;":                      '\U00002A95',
-	"elsdot;":                   '\U00002A97',
-	"emacr;":                    '\U00000113',
-	"empty;":                    '\U00002205',
-	"emptyset;":                 '\U00002205',
-	"emptyv;":                   '\U00002205',
-	"emsp;":                     '\U00002003',
-	"emsp13;":                   '\U00002004',
-	"emsp14;":                   '\U00002005',
-	"eng;":                      '\U0000014B',
-	"ensp;":                     '\U00002002',
-	"eogon;":                    '\U00000119',
-	"eopf;":                     '\U0001D556',
-	"epar;":                     '\U000022D5',
-	"eparsl;":                   '\U000029E3',
-	"eplus;":                    '\U00002A71',
-	"epsi;":                     '\U000003B5',
-	"epsilon;":                  '\U000003B5',
-	"epsiv;":                    '\U000003F5',
-	"eqcirc;":                   '\U00002256',
-	"eqcolon;":                  '\U00002255',
-	"eqsim;":                    '\U00002242',
-	"eqslantgtr;":               '\U00002A96',
-	"eqslantless;":              '\U00002A95',
-	"equals;":                   '\U0000003D',
-	"equest;":                   '\U0000225F',
-	"equiv;":                    '\U00002261',
-	"equivDD;":                  '\U00002A78',
-	"eqvparsl;":                 '\U000029E5',
-	"erDot;":                    '\U00002253',
-	"erarr;":                    '\U00002971',
-	"escr;":                     '\U0000212F',
-	"esdot;":                    '\U00002250',
-	"esim;":                     '\U00002242',
-	"eta;":                      '\U000003B7',
-	"eth;":                      '\U000000F0',
-	"euml;":                     '\U000000EB',
-	"euro;":                     '\U000020AC',
-	"excl;":                     '\U00000021',
-	"exist;":                    '\U00002203',
-	"expectation;":              '\U00002130',
-	"exponentiale;":             '\U00002147',
-	"fallingdotseq;":            '\U00002252',
-	"fcy;":                      '\U00000444',
-	"female;":                   '\U00002640',
-	"ffilig;":                   '\U0000FB03',
-	"fflig;":                    '\U0000FB00',
-	"ffllig;":                   '\U0000FB04',
-	"ffr;":                      '\U0001D523',
-	"filig;":                    '\U0000FB01',
-	"flat;":                     '\U0000266D',
-	"fllig;":                    '\U0000FB02',
-	"fltns;":                    '\U000025B1',
-	"fnof;":                     '\U00000192',
-	"fopf;":                     '\U0001D557',
-	"forall;":                   '\U00002200',
-	"fork;":                     '\U000022D4',
-	"forkv;":                    '\U00002AD9',
-	"fpartint;":                 '\U00002A0D',
-	"frac12;":                   '\U000000BD',
-	"frac13;":                   '\U00002153',
-	"frac14;":                   '\U000000BC',
-	"frac15;":                   '\U00002155',
-	"frac16;":                   '\U00002159',
-	"frac18;":                   '\U0000215B',
-	"frac23;":                   '\U00002154',
-	"frac25;":                   '\U00002156',
-	"frac34;":                   '\U000000BE',
-	"frac35;":                   '\U00002157',
-	"frac38;":                   '\U0000215C',
-	"frac45;":                   '\U00002158',
-	"frac56;":                   '\U0000215A',
-	"frac58;":                   '\U0000215D',
-	"frac78;":                   '\U0000215E',
-	"frasl;":                    '\U00002044',
-	"frown;":                    '\U00002322',
-	"fscr;":                     '\U0001D4BB',
-	"gE;":                       '\U00002267',
-	"gEl;":                      '\U00002A8C',
-	"gacute;":                   '\U000001F5',
-	"gamma;":                    '\U000003B3',
-	"gammad;":                   '\U000003DD',
-	"gap;":                      '\U00002A86',
-	"gbreve;":                   '\U0000011F',
-	"gcirc;":                    '\U0000011D',
-	"gcy;":                      '\U00000433',
-	"gdot;":                     '\U00000121',
-	"ge;":                       '\U00002265',
-	"gel;":                      '\U000022DB',
-	"geq;":                      '\U00002265',
-	"geqq;":                     '\U00002267',
-	"geqslant;":                 '\U00002A7E',
-	"ges;":                      '\U00002A7E',
-	"gescc;":                    '\U00002AA9',
-	"gesdot;":                   '\U00002A80',
-	"gesdoto;":                  '\U00002A82',
-	"gesdotol;":                 '\U00002A84',
-	"gesles;":                   '\U00002A94',
-	"gfr;":                      '\U0001D524',
-	"gg;":                       '\U0000226B',
-	"ggg;":                      '\U000022D9',
-	"gimel;":                    '\U00002137',
-	"gjcy;":                     '\U00000453',
-	"gl;":                       '\U00002277',
-	"glE;":                      '\U00002A92',
-	"gla;":                      '\U00002AA5',
-	"glj;":                      '\U00002AA4',
-	"gnE;":                      '\U00002269',
-	"gnap;":                     '\U00002A8A',
-	"gnapprox;":                 '\U00002A8A',
-	"gne;":                      '\U00002A88',
-	"gneq;":                     '\U00002A88',
-	"gneqq;":                    '\U00002269',
-	"gnsim;":                    '\U000022E7',
-	"gopf;":                     '\U0001D558',
-	"grave;":                    '\U00000060',
-	"gscr;":                     '\U0000210A',
-	"gsim;":                     '\U00002273',
-	"gsime;":                    '\U00002A8E',
-	"gsiml;":                    '\U00002A90',
-	"gt;":                       '\U0000003E',
-	"gtcc;":                     '\U00002AA7',
-	"gtcir;":                    '\U00002A7A',
-	"gtdot;":                    '\U000022D7',
-	"gtlPar;":                   '\U00002995',
-	"gtquest;":                  '\U00002A7C',
-	"gtrapprox;":                '\U00002A86',
-	"gtrarr;":                   '\U00002978',
-	"gtrdot;":                   '\U000022D7',
-	"gtreqless;":                '\U000022DB',
-	"gtreqqless;":               '\U00002A8C',
-	"gtrless;":                  '\U00002277',
-	"gtrsim;":                   '\U00002273',
-	"hArr;":                     '\U000021D4',
-	"hairsp;":                   '\U0000200A',
-	"half;":                     '\U000000BD',
-	"hamilt;":                   '\U0000210B',
-	"hardcy;":                   '\U0000044A',
-	"harr;":                     '\U00002194',
-	"harrcir;":                  '\U00002948',
-	"harrw;":                    '\U000021AD',
-	"hbar;":                     '\U0000210F',
-	"hcirc;":                    '\U00000125',
-	"hearts;":                   '\U00002665',
-	"heartsuit;":                '\U00002665',
-	"hellip;":                   '\U00002026',
-	"hercon;":                   '\U000022B9',
-	"hfr;":                      '\U0001D525',
-	"hksearow;":                 '\U00002925',
-	"hkswarow;":                 '\U00002926',
-	"hoarr;":                    '\U000021FF',
-	"homtht;":                   '\U0000223B',
-	"hookleftarrow;":            '\U000021A9',
-	"hookrightarrow;":           '\U000021AA',
-	"hopf;":                     '\U0001D559',
-	"horbar;":                   '\U00002015',
-	"hscr;":                     '\U0001D4BD',
-	"hslash;":                   '\U0000210F',
-	"hstrok;":                   '\U00000127',
-	"hybull;":                   '\U00002043',
-	"hyphen;":                   '\U00002010',
-	"iacute;":                   '\U000000ED',
-	"ic;":                       '\U00002063',
-	"icirc;":                    '\U000000EE',
-	"icy;":                      '\U00000438',
-	"iecy;":                     '\U00000435',
-	"iexcl;":                    '\U000000A1',
-	"iff;":                      '\U000021D4',
-	"ifr;":                      '\U0001D526',
-	"igrave;":                   '\U000000EC',
-	"ii;":                       '\U00002148',
-	"iiiint;":                   '\U00002A0C',
-	"iiint;":                    '\U0000222D',
-	"iinfin;":                   '\U000029DC',
-	"iiota;":                    '\U00002129',
-	"ijlig;":                    '\U00000133',
-	"imacr;":                    '\U0000012B',
-	"image;":                    '\U00002111',
-	"imagline;":                 '\U00002110',
-	"imagpart;":                 '\U00002111',
-	"imath;":                    '\U00000131',
-	"imof;":                     '\U000022B7',
-	"imped;":                    '\U000001B5',
-	"in;":                       '\U00002208',
-	"incare;":                   '\U00002105',
-	"infin;":                    '\U0000221E',
-	"infintie;":                 '\U000029DD',
-	"inodot;":                   '\U00000131',
-	"int;":                      '\U0000222B',
-	"intcal;":                   '\U000022BA',
-	"integers;":                 '\U00002124',
-	"intercal;":                 '\U000022BA',
-	"intlarhk;":                 '\U00002A17',
-	"intprod;":                  '\U00002A3C',
-	"iocy;":                     '\U00000451',
-	"iogon;":                    '\U0000012F',
-	"iopf;":                     '\U0001D55A',
-	"iota;":                     '\U000003B9',
-	"iprod;":                    '\U00002A3C',
-	"iquest;":                   '\U000000BF',
-	"iscr;":                     '\U0001D4BE',
-	"isin;":                     '\U00002208',
-	"isinE;":                    '\U000022F9',
-	"isindot;":                  '\U000022F5',
-	"isins;":                    '\U000022F4',
-	"isinsv;":                   '\U000022F3',
-	"isinv;":                    '\U00002208',
-	"it;":                       '\U00002062',
-	"itilde;":                   '\U00000129',
-	"iukcy;":                    '\U00000456',
-	"iuml;":                     '\U000000EF',
-	"jcirc;":                    '\U00000135',
-	"jcy;":                      '\U00000439',
-	"jfr;":                      '\U0001D527',
-	"jmath;":                    '\U00000237',
-	"jopf;":                     '\U0001D55B',
-	"jscr;":                     '\U0001D4BF',
-	"jsercy;":                   '\U00000458',
-	"jukcy;":                    '\U00000454',
-	"kappa;":                    '\U000003BA',
-	"kappav;":                   '\U000003F0',
-	"kcedil;":                   '\U00000137',
-	"kcy;":                      '\U0000043A',
-	"kfr;":                      '\U0001D528',
-	"kgreen;":                   '\U00000138',
-	"khcy;":                     '\U00000445',
-	"kjcy;":                     '\U0000045C',
-	"kopf;":                     '\U0001D55C',
-	"kscr;":                     '\U0001D4C0',
-	"lAarr;":                    '\U000021DA',
-	"lArr;":                     '\U000021D0',
-	"lAtail;":                   '\U0000291B',
-	"lBarr;":                    '\U0000290E',
-	"lE;":                       '\U00002266',
-	"lEg;":                      '\U00002A8B',
-	"lHar;":                     '\U00002962',
-	"lacute;":                   '\U0000013A',
-	"laemptyv;":                 '\U000029B4',
-	"lagran;":                   '\U00002112',
-	"lambda;":                   '\U000003BB',
-	"lang;":                     '\U000027E8',
-	"langd;":                    '\U00002991',
-	"langle;":                   '\U000027E8',
-	"lap;":                      '\U00002A85',
-	"laquo;":                    '\U000000AB',
-	"larr;":                     '\U00002190',
-	"larrb;":                    '\U000021E4',
-	"larrbfs;":                  '\U0000291F',
-	"larrfs;":                   '\U0000291D',
-	"larrhk;":                   '\U000021A9',
-	"larrlp;":                   '\U000021AB',
-	"larrpl;":                   '\U00002939',
-	"larrsim;":                  '\U00002973',
-	"larrtl;":                   '\U000021A2',
-	"lat;":                      '\U00002AAB',
-	"latail;":                   '\U00002919',
-	"late;":                     '\U00002AAD',
-	"lbarr;":                    '\U0000290C',
-	"lbbrk;":                    '\U00002772',
-	"lbrace;":                   '\U0000007B',
-	"lbrack;":                   '\U0000005B',
-	"lbrke;":                    '\U0000298B',
-	"lbrksld;":                  '\U0000298F',
-	"lbrkslu;":                  '\U0000298D',
-	"lcaron;":                   '\U0000013E',
-	"lcedil;":                   '\U0000013C',
-	"lceil;":                    '\U00002308',
-	"lcub;":                     '\U0000007B',
-	"lcy;":                      '\U0000043B',
-	"ldca;":                     '\U00002936',
-	"ldquo;":                    '\U0000201C',
-	"ldquor;":                   '\U0000201E',
-	"ldrdhar;":                  '\U00002967',
-	"ldrushar;":                 '\U0000294B',
-	"ldsh;":                     '\U000021B2',
-	"le;":                       '\U00002264',
-	"leftarrow;":                '\U00002190',
-	"leftarrowtail;":            '\U000021A2',
-	"leftharpoondown;":          '\U000021BD',
-	"leftharpoonup;":            '\U000021BC',
-	"leftleftarrows;":           '\U000021C7',
-	"leftrightarrow;":           '\U00002194',
-	"leftrightarrows;":          '\U000021C6',
-	"leftrightharpoons;":        '\U000021CB',
-	"leftrightsquigarrow;":      '\U000021AD',
-	"leftthreetimes;":           '\U000022CB',
-	"leg;":                      '\U000022DA',
-	"leq;":                      '\U00002264',
-	"leqq;":                     '\U00002266',
-	"leqslant;":                 '\U00002A7D',
-	"les;":                      '\U00002A7D',
-	"lescc;":                    '\U00002AA8',
-	"lesdot;":                   '\U00002A7F',
-	"lesdoto;":                  '\U00002A81',
-	"lesdotor;":                 '\U00002A83',
-	"lesges;":                   '\U00002A93',
-	"lessapprox;":               '\U00002A85',
-	"lessdot;":                  '\U000022D6',
-	"lesseqgtr;":                '\U000022DA',
-	"lesseqqgtr;":               '\U00002A8B',
-	"lessgtr;":                  '\U00002276',
-	"lesssim;":                  '\U00002272',
-	"lfisht;":                   '\U0000297C',
-	"lfloor;":                   '\U0000230A',
-	"lfr;":                      '\U0001D529',
-	"lg;":                       '\U00002276',
-	"lgE;":                      '\U00002A91',
-	"lhard;":                    '\U000021BD',
-	"lharu;":                    '\U000021BC',
-	"lharul;":                   '\U0000296A',
-	"lhblk;":                    '\U00002584',
-	"ljcy;":                     '\U00000459',
-	"ll;":                       '\U0000226A',
-	"llarr;":                    '\U000021C7',
-	"llcorner;":                 '\U0000231E',
-	"llhard;":                   '\U0000296B',
-	"lltri;":                    '\U000025FA',
-	"lmidot;":                   '\U00000140',
-	"lmoust;":                   '\U000023B0',
-	"lmoustache;":               '\U000023B0',
-	"lnE;":                      '\U00002268',
-	"lnap;":                     '\U00002A89',
-	"lnapprox;":                 '\U00002A89',
-	"lne;":                      '\U00002A87',
-	"lneq;":                     '\U00002A87',
-	"lneqq;":                    '\U00002268',
-	"lnsim;":                    '\U000022E6',
-	"loang;":                    '\U000027EC',
-	"loarr;":                    '\U000021FD',
-	"lobrk;":                    '\U000027E6',
-	"longleftarrow;":            '\U000027F5',
-	"longleftrightarrow;":       '\U000027F7',
-	"longmapsto;":               '\U000027FC',
-	"longrightarrow;":           '\U000027F6',
-	"looparrowleft;":            '\U000021AB',
-	"looparrowright;":           '\U000021AC',
-	"lopar;":                    '\U00002985',
-	"lopf;":                     '\U0001D55D',
-	"loplus;":                   '\U00002A2D',
-	"lotimes;":                  '\U00002A34',
-	"lowast;":                   '\U00002217',
-	"lowbar;":                   '\U0000005F',
-	"loz;":                      '\U000025CA',
-	"lozenge;":                  '\U000025CA',
-	"lozf;":                     '\U000029EB',
-	"lpar;":                     '\U00000028',
-	"lparlt;":                   '\U00002993',
-	"lrarr;":                    '\U000021C6',
-	"lrcorner;":                 '\U0000231F',
-	"lrhar;":                    '\U000021CB',
-	"lrhard;":                   '\U0000296D',
-	"lrm;":                      '\U0000200E',
-	"lrtri;":                    '\U000022BF',
-	"lsaquo;":                   '\U00002039',
-	"lscr;":                     '\U0001D4C1',
-	"lsh;":                      '\U000021B0',
-	"lsim;":                     '\U00002272',
-	"lsime;":                    '\U00002A8D',
-	"lsimg;":                    '\U00002A8F',
-	"lsqb;":                     '\U0000005B',
-	"lsquo;":                    '\U00002018',
-	"lsquor;":                   '\U0000201A',
-	"lstrok;":                   '\U00000142',
-	"lt;":                       '\U0000003C',
-	"ltcc;":                     '\U00002AA6',
-	"ltcir;":                    '\U00002A79',
-	"ltdot;":                    '\U000022D6',
-	"lthree;":                   '\U000022CB',
-	"ltimes;":                   '\U000022C9',
-	"ltlarr;":                   '\U00002976',
-	"ltquest;":                  '\U00002A7B',
-	"ltrPar;":                   '\U00002996',
-	"ltri;":                     '\U000025C3',
-	"ltrie;":                    '\U000022B4',
-	"ltrif;":                    '\U000025C2',
-	"lurdshar;":                 '\U0000294A',
-	"luruhar;":                  '\U00002966',
-	"mDDot;":                    '\U0000223A',
-	"macr;":                     '\U000000AF',
-	"male;":                     '\U00002642',
-	"malt;":                     '\U00002720',
-	"maltese;":                  '\U00002720',
-	"map;":                      '\U000021A6',
-	"mapsto;":                   '\U000021A6',
-	"mapstodown;":               '\U000021A7',
-	"mapstoleft;":               '\U000021A4',
-	"mapstoup;":                 '\U000021A5',
-	"marker;":                   '\U000025AE',
-	"mcomma;":                   '\U00002A29',
-	"mcy;":                      '\U0000043C',
-	"mdash;":                    '\U00002014',
-	"measuredangle;":            '\U00002221',
-	"mfr;":                      '\U0001D52A',
-	"mho;":                      '\U00002127',
-	"micro;":                    '\U000000B5',
-	"mid;":                      '\U00002223',
-	"midast;":                   '\U0000002A',
-	"midcir;":                   '\U00002AF0',
-	"middot;":                   '\U000000B7',
-	"minus;":                    '\U00002212',
-	"minusb;":                   '\U0000229F',
-	"minusd;":                   '\U00002238',
-	"minusdu;":                  '\U00002A2A',
-	"mlcp;":                     '\U00002ADB',
-	"mldr;":                     '\U00002026',
-	"mnplus;":                   '\U00002213',
-	"models;":                   '\U000022A7',
-	"mopf;":                     '\U0001D55E',
-	"mp;":                       '\U00002213',
-	"mscr;":                     '\U0001D4C2',
-	"mstpos;":                   '\U0000223E',
-	"mu;":                       '\U000003BC',
-	"multimap;":                 '\U000022B8',
-	"mumap;":                    '\U000022B8',
-	"nLeftarrow;":               '\U000021CD',
-	"nLeftrightarrow;":          '\U000021CE',
-	"nRightarrow;":              '\U000021CF',
-	"nVDash;":                   '\U000022AF',
-	"nVdash;":                   '\U000022AE',
-	"nabla;":                    '\U00002207',
-	"nacute;":                   '\U00000144',
-	"nap;":                      '\U00002249',
-	"napos;":                    '\U00000149',
-	"napprox;":                  '\U00002249',
-	"natur;":                    '\U0000266E',
-	"natural;":                  '\U0000266E',
-	"naturals;":                 '\U00002115',
-	"nbsp;":                     '\U000000A0',
-	"ncap;":                     '\U00002A43',
-	"ncaron;":                   '\U00000148',
-	"ncedil;":                   '\U00000146',
-	"ncong;":                    '\U00002247',
-	"ncup;":                     '\U00002A42',
-	"ncy;":                      '\U0000043D',
-	"ndash;":                    '\U00002013',
-	"ne;":                       '\U00002260',
-	"neArr;":                    '\U000021D7',
-	"nearhk;":                   '\U00002924',
-	"nearr;":                    '\U00002197',
-	"nearrow;":                  '\U00002197',
-	"nequiv;":                   '\U00002262',
-	"nesear;":                   '\U00002928',
-	"nexist;":                   '\U00002204',
-	"nexists;":                  '\U00002204',
-	"nfr;":                      '\U0001D52B',
-	"nge;":                      '\U00002271',
-	"ngeq;":                     '\U00002271',
-	"ngsim;":                    '\U00002275',
-	"ngt;":                      '\U0000226F',
-	"ngtr;":                     '\U0000226F',
-	"nhArr;":                    '\U000021CE',
-	"nharr;":                    '\U000021AE',
-	"nhpar;":                    '\U00002AF2',
-	"ni;":                       '\U0000220B',
-	"nis;":                      '\U000022FC',
-	"nisd;":                     '\U000022FA',
-	"niv;":                      '\U0000220B',
-	"njcy;":                     '\U0000045A',
-	"nlArr;":                    '\U000021CD',
-	"nlarr;":                    '\U0000219A',
-	"nldr;":                     '\U00002025',
-	"nle;":                      '\U00002270',
-	"nleftarrow;":               '\U0000219A',
-	"nleftrightarrow;":          '\U000021AE',
-	"nleq;":                     '\U00002270',
-	"nless;":                    '\U0000226E',
-	"nlsim;":                    '\U00002274',
-	"nlt;":                      '\U0000226E',
-	"nltri;":                    '\U000022EA',
-	"nltrie;":                   '\U000022EC',
-	"nmid;":                     '\U00002224',
-	"nopf;":                     '\U0001D55F',
-	"not;":                      '\U000000AC',
-	"notin;":                    '\U00002209',
-	"notinva;":                  '\U00002209',
-	"notinvb;":                  '\U000022F7',
-	"notinvc;":                  '\U000022F6',
-	"notni;":                    '\U0000220C',
-	"notniva;":                  '\U0000220C',
-	"notnivb;":                  '\U000022FE',
-	"notnivc;":                  '\U000022FD',
-	"npar;":                     '\U00002226',
-	"nparallel;":                '\U00002226',
-	"npolint;":                  '\U00002A14',
-	"npr;":                      '\U00002280',
-	"nprcue;":                   '\U000022E0',
-	"nprec;":                    '\U00002280',
-	"nrArr;":                    '\U000021CF',
-	"nrarr;":                    '\U0000219B',
-	"nrightarrow;":              '\U0000219B',
-	"nrtri;":                    '\U000022EB',
-	"nrtrie;":                   '\U000022ED',
-	"nsc;":                      '\U00002281',
-	"nsccue;":                   '\U000022E1',
-	"nscr;":                     '\U0001D4C3',
-	"nshortmid;":                '\U00002224',
-	"nshortparallel;":           '\U00002226',
-	"nsim;":                     '\U00002241',
-	"nsime;":                    '\U00002244',
-	"nsimeq;":                   '\U00002244',
-	"nsmid;":                    '\U00002224',
-	"nspar;":                    '\U00002226',
-	"nsqsube;":                  '\U000022E2',
-	"nsqsupe;":                  '\U000022E3',
-	"nsub;":                     '\U00002284',
-	"nsube;":                    '\U00002288',
-	"nsubseteq;":                '\U00002288',
-	"nsucc;":                    '\U00002281',
-	"nsup;":                     '\U00002285',
-	"nsupe;":                    '\U00002289',
-	"nsupseteq;":                '\U00002289',
-	"ntgl;":                     '\U00002279',
-	"ntilde;":                   '\U000000F1',
-	"ntlg;":                     '\U00002278',
-	"ntriangleleft;":            '\U000022EA',
-	"ntrianglelefteq;":          '\U000022EC',
-	"ntriangleright;":           '\U000022EB',
-	"ntrianglerighteq;":         '\U000022ED',
-	"nu;":                       '\U000003BD',
-	"num;":                      '\U00000023',
-	"numero;":                   '\U00002116',
-	"numsp;":                    '\U00002007',
-	"nvDash;":                   '\U000022AD',
-	"nvHarr;":                   '\U00002904',
-	"nvdash;":                   '\U000022AC',
-	"nvinfin;":                  '\U000029DE',
-	"nvlArr;":                   '\U00002902',
-	"nvrArr;":                   '\U00002903',
-	"nwArr;":                    '\U000021D6',
-	"nwarhk;":                   '\U00002923',
-	"nwarr;":                    '\U00002196',
-	"nwarrow;":                  '\U00002196',
-	"nwnear;":                   '\U00002927',
-	"oS;":                       '\U000024C8',
-	"oacute;":                   '\U000000F3',
-	"oast;":                     '\U0000229B',
-	"ocir;":                     '\U0000229A',
-	"ocirc;":                    '\U000000F4',
-	"ocy;":                      '\U0000043E',
-	"odash;":                    '\U0000229D',
-	"odblac;":                   '\U00000151',
-	"odiv;":                     '\U00002A38',
-	"odot;":                     '\U00002299',
-	"odsold;":                   '\U000029BC',
-	"oelig;":                    '\U00000153',
-	"ofcir;":                    '\U000029BF',
-	"ofr;":                      '\U0001D52C',
-	"ogon;":                     '\U000002DB',
-	"ograve;":                   '\U000000F2',
-	"ogt;":                      '\U000029C1',
-	"ohbar;":                    '\U000029B5',
-	"ohm;":                      '\U000003A9',
-	"oint;":                     '\U0000222E',
-	"olarr;":                    '\U000021BA',
-	"olcir;":                    '\U000029BE',
-	"olcross;":                  '\U000029BB',
-	"oline;":                    '\U0000203E',
-	"olt;":                      '\U000029C0',
-	"omacr;":                    '\U0000014D',
-	"omega;":                    '\U000003C9',
-	"omicron;":                  '\U000003BF',
-	"omid;":                     '\U000029B6',
-	"ominus;":                   '\U00002296',
-	"oopf;":                     '\U0001D560',
-	"opar;":                     '\U000029B7',
-	"operp;":                    '\U000029B9',
-	"oplus;":                    '\U00002295',
-	"or;":                       '\U00002228',
-	"orarr;":                    '\U000021BB',
-	"ord;":                      '\U00002A5D',
-	"order;":                    '\U00002134',
-	"orderof;":                  '\U00002134',
-	"ordf;":                     '\U000000AA',
-	"ordm;":                     '\U000000BA',
-	"origof;":                   '\U000022B6',
-	"oror;":                     '\U00002A56',
-	"orslope;":                  '\U00002A57',
-	"orv;":                      '\U00002A5B',
-	"oscr;":                     '\U00002134',
-	"oslash;":                   '\U000000F8',
-	"osol;":                     '\U00002298',
-	"otilde;":                   '\U000000F5',
-	"otimes;":                   '\U00002297',
-	"otimesas;":                 '\U00002A36',
-	"ouml;":                     '\U000000F6',
-	"ovbar;":                    '\U0000233D',
-	"par;":                      '\U00002225',
-	"para;":                     '\U000000B6',
-	"parallel;":                 '\U00002225',
-	"parsim;":                   '\U00002AF3',
-	"parsl;":                    '\U00002AFD',
-	"part;":                     '\U00002202',
-	"pcy;":                      '\U0000043F',
-	"percnt;":                   '\U00000025',
-	"period;":                   '\U0000002E',
-	"permil;":                   '\U00002030',
-	"perp;":                     '\U000022A5',
-	"pertenk;":                  '\U00002031',
-	"pfr;":                      '\U0001D52D',
-	"phi;":                      '\U000003C6',
-	"phiv;":                     '\U000003D5',
-	"phmmat;":                   '\U00002133',
-	"phone;":                    '\U0000260E',
-	"pi;":                       '\U000003C0',
-	"pitchfork;":                '\U000022D4',
-	"piv;":                      '\U000003D6',
-	"planck;":                   '\U0000210F',
-	"planckh;":                  '\U0000210E',
-	"plankv;":                   '\U0000210F',
-	"plus;":                     '\U0000002B',
-	"plusacir;":                 '\U00002A23',
-	"plusb;":                    '\U0000229E',
-	"pluscir;":                  '\U00002A22',
-	"plusdo;":                   '\U00002214',
-	"plusdu;":                   '\U00002A25',
-	"pluse;":                    '\U00002A72',
-	"plusmn;":                   '\U000000B1',
-	"plussim;":                  '\U00002A26',
-	"plustwo;":                  '\U00002A27',
-	"pm;":                       '\U000000B1',
-	"pointint;":                 '\U00002A15',
-	"popf;":                     '\U0001D561',
-	"pound;":                    '\U000000A3',
-	"pr;":                       '\U0000227A',
-	"prE;":                      '\U00002AB3',
-	"prap;":                     '\U00002AB7',
-	"prcue;":                    '\U0000227C',
-	"pre;":                      '\U00002AAF',
-	"prec;":                     '\U0000227A',
-	"precapprox;":               '\U00002AB7',
-	"preccurlyeq;":              '\U0000227C',
-	"preceq;":                   '\U00002AAF',
-	"precnapprox;":              '\U00002AB9',
-	"precneqq;":                 '\U00002AB5',
-	"precnsim;":                 '\U000022E8',
-	"precsim;":                  '\U0000227E',
-	"prime;":                    '\U00002032',
-	"primes;":                   '\U00002119',
-	"prnE;":                     '\U00002AB5',
-	"prnap;":                    '\U00002AB9',
-	"prnsim;":                   '\U000022E8',
-	"prod;":                     '\U0000220F',
-	"profalar;":                 '\U0000232E',
-	"profline;":                 '\U00002312',
-	"profsurf;":                 '\U00002313',
-	"prop;":                     '\U0000221D',
-	"propto;":                   '\U0000221D',
-	"prsim;":                    '\U0000227E',
-	"prurel;":                   '\U000022B0',
-	"pscr;":                     '\U0001D4C5',
-	"psi;":                      '\U000003C8',
-	"puncsp;":                   '\U00002008',
-	"qfr;":                      '\U0001D52E',
-	"qint;":                     '\U00002A0C',
-	"qopf;":                     '\U0001D562',
-	"qprime;":                   '\U00002057',
-	"qscr;":                     '\U0001D4C6',
-	"quaternions;":              '\U0000210D',
-	"quatint;":                  '\U00002A16',
-	"quest;":                    '\U0000003F',
-	"questeq;":                  '\U0000225F',
-	"quot;":                     '\U00000022',
-	"rAarr;":                    '\U000021DB',
-	"rArr;":                     '\U000021D2',
-	"rAtail;":                   '\U0000291C',
-	"rBarr;":                    '\U0000290F',
-	"rHar;":                     '\U00002964',
-	"racute;":                   '\U00000155',
-	"radic;":                    '\U0000221A',
-	"raemptyv;":                 '\U000029B3',
-	"rang;":                     '\U000027E9',
-	"rangd;":                    '\U00002992',
-	"range;":                    '\U000029A5',
-	"rangle;":                   '\U000027E9',
-	"raquo;":                    '\U000000BB',
-	"rarr;":                     '\U00002192',
-	"rarrap;":                   '\U00002975',
-	"rarrb;":                    '\U000021E5',
-	"rarrbfs;":                  '\U00002920',
-	"rarrc;":                    '\U00002933',
-	"rarrfs;":                   '\U0000291E',
-	"rarrhk;":                   '\U000021AA',
-	"rarrlp;":                   '\U000021AC',
-	"rarrpl;":                   '\U00002945',
-	"rarrsim;":                  '\U00002974',
-	"rarrtl;":                   '\U000021A3',
-	"rarrw;":                    '\U0000219D',
-	"ratail;":                   '\U0000291A',
-	"ratio;":                    '\U00002236',
-	"rationals;":                '\U0000211A',
-	"rbarr;":                    '\U0000290D',
-	"rbbrk;":                    '\U00002773',
-	"rbrace;":                   '\U0000007D',
-	"rbrack;":                   '\U0000005D',
-	"rbrke;":                    '\U0000298C',
-	"rbrksld;":                  '\U0000298E',
-	"rbrkslu;":                  '\U00002990',
-	"rcaron;":                   '\U00000159',
-	"rcedil;":                   '\U00000157',
-	"rceil;":                    '\U00002309',
-	"rcub;":                     '\U0000007D',
-	"rcy;":                      '\U00000440',
-	"rdca;":                     '\U00002937',
-	"rdldhar;":                  '\U00002969',
-	"rdquo;":                    '\U0000201D',
-	"rdquor;":                   '\U0000201D',
-	"rdsh;":                     '\U000021B3',
-	"real;":                     '\U0000211C',
-	"realine;":                  '\U0000211B',
-	"realpart;":                 '\U0000211C',
-	"reals;":                    '\U0000211D',
-	"rect;":                     '\U000025AD',
-	"reg;":                      '\U000000AE',
-	"rfisht;":                   '\U0000297D',
-	"rfloor;":                   '\U0000230B',
-	"rfr;":                      '\U0001D52F',
-	"rhard;":                    '\U000021C1',
-	"rharu;":                    '\U000021C0',
-	"rharul;":                   '\U0000296C',
-	"rho;":                      '\U000003C1',
-	"rhov;":                     '\U000003F1',
-	"rightarrow;":               '\U00002192',
-	"rightarrowtail;":           '\U000021A3',
-	"rightharpoondown;":         '\U000021C1',
-	"rightharpoonup;":           '\U000021C0',
-	"rightleftarrows;":          '\U000021C4',
-	"rightleftharpoons;":        '\U000021CC',
-	"rightrightarrows;":         '\U000021C9',
-	"rightsquigarrow;":          '\U0000219D',
-	"rightthreetimes;":          '\U000022CC',
-	"ring;":                     '\U000002DA',
-	"risingdotseq;":             '\U00002253',
-	"rlarr;":                    '\U000021C4',
-	"rlhar;":                    '\U000021CC',
-	"rlm;":                      '\U0000200F',
-	"rmoust;":                   '\U000023B1',
-	"rmoustache;":               '\U000023B1',
-	"rnmid;":                    '\U00002AEE',
-	"roang;":                    '\U000027ED',
-	"roarr;":                    '\U000021FE',
-	"robrk;":                    '\U000027E7',
-	"ropar;":                    '\U00002986',
-	"ropf;":                     '\U0001D563',
-	"roplus;":                   '\U00002A2E',
-	"rotimes;":                  '\U00002A35',
-	"rpar;":                     '\U00000029',
-	"rpargt;":                   '\U00002994',
-	"rppolint;":                 '\U00002A12',
-	"rrarr;":                    '\U000021C9',
-	"rsaquo;":                   '\U0000203A',
-	"rscr;":                     '\U0001D4C7',
-	"rsh;":                      '\U000021B1',
-	"rsqb;":                     '\U0000005D',
-	"rsquo;":                    '\U00002019',
-	"rsquor;":                   '\U00002019',
-	"rthree;":                   '\U000022CC',
-	"rtimes;":                   '\U000022CA',
-	"rtri;":                     '\U000025B9',
-	"rtrie;":                    '\U000022B5',
-	"rtrif;":                    '\U000025B8',
-	"rtriltri;":                 '\U000029CE',
-	"ruluhar;":                  '\U00002968',
-	"rx;":                       '\U0000211E',
-	"sacute;":                   '\U0000015B',
-	"sbquo;":                    '\U0000201A',
-	"sc;":                       '\U0000227B',
-	"scE;":                      '\U00002AB4',
-	"scap;":                     '\U00002AB8',
-	"scaron;":                   '\U00000161',
-	"sccue;":                    '\U0000227D',
-	"sce;":                      '\U00002AB0',
-	"scedil;":                   '\U0000015F',
-	"scirc;":                    '\U0000015D',
-	"scnE;":                     '\U00002AB6',
-	"scnap;":                    '\U00002ABA',
-	"scnsim;":                   '\U000022E9',
-	"scpolint;":                 '\U00002A13',
-	"scsim;":                    '\U0000227F',
-	"scy;":                      '\U00000441',
-	"sdot;":                     '\U000022C5',
-	"sdotb;":                    '\U000022A1',
-	"sdote;":                    '\U00002A66',
-	"seArr;":                    '\U000021D8',
-	"searhk;":                   '\U00002925',
-	"searr;":                    '\U00002198',
-	"searrow;":                  '\U00002198',
-	"sect;":                     '\U000000A7',
-	"semi;":                     '\U0000003B',
-	"seswar;":                   '\U00002929',
-	"setminus;":                 '\U00002216',
-	"setmn;":                    '\U00002216',
-	"sext;":                     '\U00002736',
-	"sfr;":                      '\U0001D530',
-	"sfrown;":                   '\U00002322',
-	"sharp;":                    '\U0000266F',
-	"shchcy;":                   '\U00000449',
-	"shcy;":                     '\U00000448',
-	"shortmid;":                 '\U00002223',
-	"shortparallel;":            '\U00002225',
-	"shy;":                      '\U000000AD',
-	"sigma;":                    '\U000003C3',
-	"sigmaf;":                   '\U000003C2',
-	"sigmav;":                   '\U000003C2',
-	"sim;":                      '\U0000223C',
-	"simdot;":                   '\U00002A6A',
-	"sime;":                     '\U00002243',
-	"simeq;":                    '\U00002243',
-	"simg;":                     '\U00002A9E',
-	"simgE;":                    '\U00002AA0',
-	"siml;":                     '\U00002A9D',
-	"simlE;":                    '\U00002A9F',
-	"simne;":                    '\U00002246',
-	"simplus;":                  '\U00002A24',
-	"simrarr;":                  '\U00002972',
-	"slarr;":                    '\U00002190',
-	"smallsetminus;":            '\U00002216',
-	"smashp;":                   '\U00002A33',
-	"smeparsl;":                 '\U000029E4',
-	"smid;":                     '\U00002223',
-	"smile;":                    '\U00002323',
-	"smt;":                      '\U00002AAA',
-	"smte;":                     '\U00002AAC',
-	"softcy;":                   '\U0000044C',
-	"sol;":                      '\U0000002F',
-	"solb;":                     '\U000029C4',
-	"solbar;":                   '\U0000233F',
-	"sopf;":                     '\U0001D564',
-	"spades;":                   '\U00002660',
-	"spadesuit;":                '\U00002660',
-	"spar;":                     '\U00002225',
-	"sqcap;":                    '\U00002293',
-	"sqcup;":                    '\U00002294',
-	"sqsub;":                    '\U0000228F',
-	"sqsube;":                   '\U00002291',
-	"sqsubset;":                 '\U0000228F',
-	"sqsubseteq;":               '\U00002291',
-	"sqsup;":                    '\U00002290',
-	"sqsupe;":                   '\U00002292',
-	"sqsupset;":                 '\U00002290',
-	"sqsupseteq;":               '\U00002292',
-	"squ;":                      '\U000025A1',
-	"square;":                   '\U000025A1',
-	"squarf;":                   '\U000025AA',
-	"squf;":                     '\U000025AA',
-	"srarr;":                    '\U00002192',
-	"sscr;":                     '\U0001D4C8',
-	"ssetmn;":                   '\U00002216',
-	"ssmile;":                   '\U00002323',
-	"sstarf;":                   '\U000022C6',
-	"star;":                     '\U00002606',
-	"starf;":                    '\U00002605',
-	"straightepsilon;":          '\U000003F5',
-	"straightphi;":              '\U000003D5',
-	"strns;":                    '\U000000AF',
-	"sub;":                      '\U00002282',
-	"subE;":                     '\U00002AC5',
-	"subdot;":                   '\U00002ABD',
-	"sube;":                     '\U00002286',
-	"subedot;":                  '\U00002AC3',
-	"submult;":                  '\U00002AC1',
-	"subnE;":                    '\U00002ACB',
-	"subne;":                    '\U0000228A',
-	"subplus;":                  '\U00002ABF',
-	"subrarr;":                  '\U00002979',
-	"subset;":                   '\U00002282',
-	"subseteq;":                 '\U00002286',
-	"subseteqq;":                '\U00002AC5',
-	"subsetneq;":                '\U0000228A',
-	"subsetneqq;":               '\U00002ACB',
-	"subsim;":                   '\U00002AC7',
-	"subsub;":                   '\U00002AD5',
-	"subsup;":                   '\U00002AD3',
-	"succ;":                     '\U0000227B',
-	"succapprox;":               '\U00002AB8',
-	"succcurlyeq;":              '\U0000227D',
-	"succeq;":                   '\U00002AB0',
-	"succnapprox;":              '\U00002ABA',
-	"succneqq;":                 '\U00002AB6',
-	"succnsim;":                 '\U000022E9',
-	"succsim;":                  '\U0000227F',
-	"sum;":                      '\U00002211',
-	"sung;":                     '\U0000266A',
-	"sup;":                      '\U00002283',
-	"sup1;":                     '\U000000B9',
-	"sup2;":                     '\U000000B2',
-	"sup3;":                     '\U000000B3',
-	"supE;":                     '\U00002AC6',
-	"supdot;":                   '\U00002ABE',
-	"supdsub;":                  '\U00002AD8',
-	"supe;":                     '\U00002287',
-	"supedot;":                  '\U00002AC4',
-	"suphsol;":                  '\U000027C9',
-	"suphsub;":                  '\U00002AD7',
-	"suplarr;":                  '\U0000297B',
-	"supmult;":                  '\U00002AC2',
-	"supnE;":                    '\U00002ACC',
-	"supne;":                    '\U0000228B',
-	"supplus;":                  '\U00002AC0',
-	"supset;":                   '\U00002283',
-	"supseteq;":                 '\U00002287',
-	"supseteqq;":                '\U00002AC6',
-	"supsetneq;":                '\U0000228B',
-	"supsetneqq;":               '\U00002ACC',
-	"supsim;":                   '\U00002AC8',
-	"supsub;":                   '\U00002AD4',
-	"supsup;":                   '\U00002AD6',
-	"swArr;":                    '\U000021D9',
-	"swarhk;":                   '\U00002926',
-	"swarr;":                    '\U00002199',
-	"swarrow;":                  '\U00002199',
-	"swnwar;":                   '\U0000292A',
-	"szlig;":                    '\U000000DF',
-	"target;":                   '\U00002316',
-	"tau;":                      '\U000003C4',
-	"tbrk;":                     '\U000023B4',
-	"tcaron;":                   '\U00000165',
-	"tcedil;":                   '\U00000163',
-	"tcy;":                      '\U00000442',
-	"tdot;":                     '\U000020DB',
-	"telrec;":                   '\U00002315',
-	"tfr;":                      '\U0001D531',
-	"there4;":                   '\U00002234',
-	"therefore;":                '\U00002234',
-	"theta;":                    '\U000003B8',
-	"thetasym;":                 '\U000003D1',
-	"thetav;":                   '\U000003D1',
-	"thickapprox;":              '\U00002248',
-	"thicksim;":                 '\U0000223C',
-	"thinsp;":                   '\U00002009',
-	"thkap;":                    '\U00002248',
-	"thksim;":                   '\U0000223C',
-	"thorn;":                    '\U000000FE',
-	"tilde;":                    '\U000002DC',
-	"times;":                    '\U000000D7',
-	"timesb;":                   '\U000022A0',
-	"timesbar;":                 '\U00002A31',
-	"timesd;":                   '\U00002A30',
-	"tint;":                     '\U0000222D',
-	"toea;":                     '\U00002928',
-	"top;":                      '\U000022A4',
-	"topbot;":                   '\U00002336',
-	"topcir;":                   '\U00002AF1',
-	"topf;":                     '\U0001D565',
-	"topfork;":                  '\U00002ADA',
-	"tosa;":                     '\U00002929',
-	"tprime;":                   '\U00002034',
-	"trade;":                    '\U00002122',
-	"triangle;":                 '\U000025B5',
-	"triangledown;":             '\U000025BF',
-	"triangleleft;":             '\U000025C3',
-	"trianglelefteq;":           '\U000022B4',
-	"triangleq;":                '\U0000225C',
-	"triangleright;":            '\U000025B9',
-	"trianglerighteq;":          '\U000022B5',
-	"tridot;":                   '\U000025EC',
-	"trie;":                     '\U0000225C',
-	"triminus;":                 '\U00002A3A',
-	"triplus;":                  '\U00002A39',
-	"trisb;":                    '\U000029CD',
-	"tritime;":                  '\U00002A3B',
-	"trpezium;":                 '\U000023E2',
-	"tscr;":                     '\U0001D4C9',
-	"tscy;":                     '\U00000446',
-	"tshcy;":                    '\U0000045B',
-	"tstrok;":                   '\U00000167',
-	"twixt;":                    '\U0000226C',
-	"twoheadleftarrow;":         '\U0000219E',
-	"twoheadrightarrow;":        '\U000021A0',
-	"uArr;":                     '\U000021D1',
-	"uHar;":                     '\U00002963',
-	"uacute;":                   '\U000000FA',
-	"uarr;":                     '\U00002191',
-	"ubrcy;":                    '\U0000045E',
-	"ubreve;":                   '\U0000016D',
-	"ucirc;":                    '\U000000FB',
-	"ucy;":                      '\U00000443',
-	"udarr;":                    '\U000021C5',
-	"udblac;":                   '\U00000171',
-	"udhar;":                    '\U0000296E',
-	"ufisht;":                   '\U0000297E',
-	"ufr;":                      '\U0001D532',
-	"ugrave;":                   '\U000000F9',
-	"uharl;":                    '\U000021BF',
-	"uharr;":                    '\U000021BE',
-	"uhblk;":                    '\U00002580',
-	"ulcorn;":                   '\U0000231C',
-	"ulcorner;":                 '\U0000231C',
-	"ulcrop;":                   '\U0000230F',
-	"ultri;":                    '\U000025F8',
-	"umacr;":                    '\U0000016B',
-	"uml;":                      '\U000000A8',
-	"uogon;":                    '\U00000173',
-	"uopf;":                     '\U0001D566',
-	"uparrow;":                  '\U00002191',
-	"updownarrow;":              '\U00002195',
-	"upharpoonleft;":            '\U000021BF',
-	"upharpoonright;":           '\U000021BE',
-	"uplus;":                    '\U0000228E',
-	"upsi;":                     '\U000003C5',
-	"upsih;":                    '\U000003D2',
-	"upsilon;":                  '\U000003C5',
-	"upuparrows;":               '\U000021C8',
-	"urcorn;":                   '\U0000231D',
-	"urcorner;":                 '\U0000231D',
-	"urcrop;":                   '\U0000230E',
-	"uring;":                    '\U0000016F',
-	"urtri;":                    '\U000025F9',
-	"uscr;":                     '\U0001D4CA',
-	"utdot;":                    '\U000022F0',
-	"utilde;":                   '\U00000169',
-	"utri;":                     '\U000025B5',
-	"utrif;":                    '\U000025B4',
-	"uuarr;":                    '\U000021C8',
-	"uuml;":                     '\U000000FC',
-	"uwangle;":                  '\U000029A7',
-	"vArr;":                     '\U000021D5',
-	"vBar;":                     '\U00002AE8',
-	"vBarv;":                    '\U00002AE9',
-	"vDash;":                    '\U000022A8',
-	"vangrt;":                   '\U0000299C',
-	"varepsilon;":               '\U000003F5',
-	"varkappa;":                 '\U000003F0',
-	"varnothing;":               '\U00002205',
-	"varphi;":                   '\U000003D5',
-	"varpi;":                    '\U000003D6',
-	"varpropto;":                '\U0000221D',
-	"varr;":                     '\U00002195',
-	"varrho;":                   '\U000003F1',
-	"varsigma;":                 '\U000003C2',
-	"vartheta;":                 '\U000003D1',
-	"vartriangleleft;":          '\U000022B2',
-	"vartriangleright;":         '\U000022B3',
-	"vcy;":                      '\U00000432',
-	"vdash;":                    '\U000022A2',
-	"vee;":                      '\U00002228',
-	"veebar;":                   '\U000022BB',
-	"veeeq;":                    '\U0000225A',
-	"vellip;":                   '\U000022EE',
-	"verbar;":                   '\U0000007C',
-	"vert;":                     '\U0000007C',
-	"vfr;":                      '\U0001D533',
-	"vltri;":                    '\U000022B2',
-	"vopf;":                     '\U0001D567',
-	"vprop;":                    '\U0000221D',
-	"vrtri;":                    '\U000022B3',
-	"vscr;":                     '\U0001D4CB',
-	"vzigzag;":                  '\U0000299A',
-	"wcirc;":                    '\U00000175',
-	"wedbar;":                   '\U00002A5F',
-	"wedge;":                    '\U00002227',
-	"wedgeq;":                   '\U00002259',
-	"weierp;":                   '\U00002118',
-	"wfr;":                      '\U0001D534',
-	"wopf;":                     '\U0001D568',
-	"wp;":                       '\U00002118',
-	"wr;":                       '\U00002240',
-	"wreath;":                   '\U00002240',
-	"wscr;":                     '\U0001D4CC',
-	"xcap;":                     '\U000022C2',
-	"xcirc;":                    '\U000025EF',
-	"xcup;":                     '\U000022C3',
-	"xdtri;":                    '\U000025BD',
-	"xfr;":                      '\U0001D535',
-	"xhArr;":                    '\U000027FA',
-	"xharr;":                    '\U000027F7',
-	"xi;":                       '\U000003BE',
-	"xlArr;":                    '\U000027F8',
-	"xlarr;":                    '\U000027F5',
-	"xmap;":                     '\U000027FC',
-	"xnis;":                     '\U000022FB',
-	"xodot;":                    '\U00002A00',
-	"xopf;":                     '\U0001D569',
-	"xoplus;":                   '\U00002A01',
-	"xotime;":                   '\U00002A02',
-	"xrArr;":                    '\U000027F9',
-	"xrarr;":                    '\U000027F6',
-	"xscr;":                     '\U0001D4CD',
-	"xsqcup;":                   '\U00002A06',
-	"xuplus;":                   '\U00002A04',
-	"xutri;":                    '\U000025B3',
-	"xvee;":                     '\U000022C1',
-	"xwedge;":                   '\U000022C0',
-	"yacute;":                   '\U000000FD',
-	"yacy;":                     '\U0000044F',
-	"ycirc;":                    '\U00000177',
-	"ycy;":                      '\U0000044B',
-	"yen;":                      '\U000000A5',
-	"yfr;":                      '\U0001D536',
-	"yicy;":                     '\U00000457',
-	"yopf;":                     '\U0001D56A',
-	"yscr;":                     '\U0001D4CE',
-	"yucy;":                     '\U0000044E',
-	"yuml;":                     '\U000000FF',
-	"zacute;":                   '\U0000017A',
-	"zcaron;":                   '\U0000017E',
-	"zcy;":                      '\U00000437',
-	"zdot;":                     '\U0000017C',
-	"zeetrf;":                   '\U00002128',
-	"zeta;":                     '\U000003B6',
-	"zfr;":                      '\U0001D537',
-	"zhcy;":                     '\U00000436',
-	"zigrarr;":                  '\U000021DD',
-	"zopf;":                     '\U0001D56B',
-	"zscr;":                     '\U0001D4CF',
-	"zwj;":                      '\U0000200D',
-	"zwnj;":                     '\U0000200C',
-	"AElig":                     '\U000000C6',
-	"AMP":                       '\U00000026',
-	"Aacute":                    '\U000000C1',
-	"Acirc":                     '\U000000C2',
-	"Agrave":                    '\U000000C0',
-	"Aring":                     '\U000000C5',
-	"Atilde":                    '\U000000C3',
-	"Auml":                      '\U000000C4',
-	"COPY":                      '\U000000A9',
-	"Ccedil":                    '\U000000C7',
-	"ETH":                       '\U000000D0',
-	"Eacute":                    '\U000000C9',
-	"Ecirc":                     '\U000000CA',
-	"Egrave":                    '\U000000C8',
-	"Euml":                      '\U000000CB',
-	"GT":                        '\U0000003E',
-	"Iacute":                    '\U000000CD',
-	"Icirc":                     '\U000000CE',
-	"Igrave":                    '\U000000CC',
-	"Iuml":                      '\U000000CF',
-	"LT":                        '\U0000003C',
-	"Ntilde":                    '\U000000D1',
-	"Oacute":                    '\U000000D3',
-	"Ocirc":                     '\U000000D4',
-	"Ograve":                    '\U000000D2',
-	"Oslash":                    '\U000000D8',
-	"Otilde":                    '\U000000D5',
-	"Ouml":                      '\U000000D6',
-	"QUOT":                      '\U00000022',
-	"REG":                       '\U000000AE',
-	"THORN":                     '\U000000DE',
-	"Uacute":                    '\U000000DA',
-	"Ucirc":                     '\U000000DB',
-	"Ugrave":                    '\U000000D9',
-	"Uuml":                      '\U000000DC',
-	"Yacute":                    '\U000000DD',
-	"aacute":                    '\U000000E1',
-	"acirc":                     '\U000000E2',
-	"acute":                     '\U000000B4',
-	"aelig":                     '\U000000E6',
-	"agrave":                    '\U000000E0',
-	"amp":                       '\U00000026',
-	"aring":                     '\U000000E5',
-	"atilde":                    '\U000000E3',
-	"auml":                      '\U000000E4',
-	"brvbar":                    '\U000000A6',
-	"ccedil":                    '\U000000E7',
-	"cedil":                     '\U000000B8',
-	"cent":                      '\U000000A2',
-	"copy":                      '\U000000A9',
-	"curren":                    '\U000000A4',
-	"deg":                       '\U000000B0',
-	"divide":                    '\U000000F7',
-	"eacute":                    '\U000000E9',
-	"ecirc":                     '\U000000EA',
-	"egrave":                    '\U000000E8',
-	"eth":                       '\U000000F0',
-	"euml":                      '\U000000EB',
-	"frac12":                    '\U000000BD',
-	"frac14":                    '\U000000BC',
-	"frac34":                    '\U000000BE',
-	"gt":                        '\U0000003E',
-	"iacute":                    '\U000000ED',
-	"icirc":                     '\U000000EE',
-	"iexcl":                     '\U000000A1',
-	"igrave":                    '\U000000EC',
-	"iquest":                    '\U000000BF',
-	"iuml":                      '\U000000EF',
-	"laquo":                     '\U000000AB',
-	"lt":                        '\U0000003C',
-	"macr":                      '\U000000AF',
-	"micro":                     '\U000000B5',
-	"middot":                    '\U000000B7',
-	"nbsp":                      '\U000000A0',
-	"not":                       '\U000000AC',
-	"ntilde":                    '\U000000F1',
-	"oacute":                    '\U000000F3',
-	"ocirc":                     '\U000000F4',
-	"ograve":                    '\U000000F2',
-	"ordf":                      '\U000000AA',
-	"ordm":                      '\U000000BA',
-	"oslash":                    '\U000000F8',
-	"otilde":                    '\U000000F5',
-	"ouml":                      '\U000000F6',
-	"para":                      '\U000000B6',
-	"plusmn":                    '\U000000B1',
-	"pound":                     '\U000000A3',
-	"quot":                      '\U00000022',
-	"raquo":                     '\U000000BB',
-	"reg":                       '\U000000AE',
-	"sect":                      '\U000000A7',
-	"shy":                       '\U000000AD',
-	"sup1":                      '\U000000B9',
-	"sup2":                      '\U000000B2',
-	"sup3":                      '\U000000B3',
-	"szlig":                     '\U000000DF',
-	"thorn":                     '\U000000FE',
-	"times":                     '\U000000D7',
-	"uacute":                    '\U000000FA',
-	"ucirc":                     '\U000000FB',
-	"ugrave":                    '\U000000F9',
-	"uml":                       '\U000000A8',
-	"uuml":                      '\U000000FC',
-	"yacute":                    '\U000000FD',
-	"yen":                       '\U000000A5',
-	"yuml":                      '\U000000FF',
-}
+var entity map[string]rune
 
 // HTML entities that are two unicode codepoints.
-var entity2 = map[string][2]rune{
-	// TODO(nigeltao): Handle replacements that are wider than their names.
-	// "nLt;":                     {'\u226A', '\u20D2'},
-	// "nGt;":                     {'\u226B', '\u20D2'},
-	"NotEqualTilde;":           {'\u2242', '\u0338'},
-	"NotGreaterFullEqual;":     {'\u2267', '\u0338'},
-	"NotGreaterGreater;":       {'\u226B', '\u0338'},
-	"NotGreaterSlantEqual;":    {'\u2A7E', '\u0338'},
-	"NotHumpDownHump;":         {'\u224E', '\u0338'},
-	"NotHumpEqual;":            {'\u224F', '\u0338'},
-	"NotLeftTriangleBar;":      {'\u29CF', '\u0338'},
-	"NotLessLess;":             {'\u226A', '\u0338'},
-	"NotLessSlantEqual;":       {'\u2A7D', '\u0338'},
-	"NotNestedGreaterGreater;": {'\u2AA2', '\u0338'},
-	"NotNestedLessLess;":       {'\u2AA1', '\u0338'},
-	"NotPrecedesEqual;":        {'\u2AAF', '\u0338'},
-	"NotRightTriangleBar;":     {'\u29D0', '\u0338'},
-	"NotSquareSubset;":         {'\u228F', '\u0338'},
-	"NotSquareSuperset;":       {'\u2290', '\u0338'},
-	"NotSubset;":               {'\u2282', '\u20D2'},
-	"NotSucceedsEqual;":        {'\u2AB0', '\u0338'},
-	"NotSucceedsTilde;":        {'\u227F', '\u0338'},
-	"NotSuperset;":             {'\u2283', '\u20D2'},
-	"ThickSpace;":              {'\u205F', '\u200A'},
-	"acE;":                     {'\u223E', '\u0333'},
-	"bne;":                     {'\u003D', '\u20E5'},
-	"bnequiv;":                 {'\u2261', '\u20E5'},
-	"caps;":                    {'\u2229', '\uFE00'},
-	"cups;":                    {'\u222A', '\uFE00'},
-	"fjlig;":                   {'\u0066', '\u006A'},
-	"gesl;":                    {'\u22DB', '\uFE00'},
-	"gvertneqq;":               {'\u2269', '\uFE00'},
-	"gvnE;":                    {'\u2269', '\uFE00'},
-	"lates;":                   {'\u2AAD', '\uFE00'},
-	"lesg;":                    {'\u22DA', '\uFE00'},
-	"lvertneqq;":               {'\u2268', '\uFE00'},
-	"lvnE;":                    {'\u2268', '\uFE00'},
-	"nGg;":                     {'\u22D9', '\u0338'},
-	"nGtv;":                    {'\u226B', '\u0338'},
-	"nLl;":                     {'\u22D8', '\u0338'},
-	"nLtv;":                    {'\u226A', '\u0338'},
-	"nang;":                    {'\u2220', '\u20D2'},
-	"napE;":                    {'\u2A70', '\u0338'},
-	"napid;":                   {'\u224B', '\u0338'},
-	"nbump;":                   {'\u224E', '\u0338'},
-	"nbumpe;":                  {'\u224F', '\u0338'},
-	"ncongdot;":                {'\u2A6D', '\u0338'},
-	"nedot;":                   {'\u2250', '\u0338'},
-	"nesim;":                   {'\u2242', '\u0338'},
-	"ngE;":                     {'\u2267', '\u0338'},
-	"ngeqq;":                   {'\u2267', '\u0338'},
-	"ngeqslant;":               {'\u2A7E', '\u0338'},
-	"nges;":                    {'\u2A7E', '\u0338'},
-	"nlE;":                     {'\u2266', '\u0338'},
-	"nleqq;":                   {'\u2266', '\u0338'},
-	"nleqslant;":               {'\u2A7D', '\u0338'},
-	"nles;":                    {'\u2A7D', '\u0338'},
-	"notinE;":                  {'\u22F9', '\u0338'},
-	"notindot;":                {'\u22F5', '\u0338'},
-	"nparsl;":                  {'\u2AFD', '\u20E5'},
-	"npart;":                   {'\u2202', '\u0338'},
-	"npre;":                    {'\u2AAF', '\u0338'},
-	"npreceq;":                 {'\u2AAF', '\u0338'},
-	"nrarrc;":                  {'\u2933', '\u0338'},
-	"nrarrw;":                  {'\u219D', '\u0338'},
-	"nsce;":                    {'\u2AB0', '\u0338'},
-	"nsubE;":                   {'\u2AC5', '\u0338'},
-	"nsubset;":                 {'\u2282', '\u20D2'},
-	"nsubseteqq;":              {'\u2AC5', '\u0338'},
-	"nsucceq;":                 {'\u2AB0', '\u0338'},
-	"nsupE;":                   {'\u2AC6', '\u0338'},
-	"nsupset;":                 {'\u2283', '\u20D2'},
-	"nsupseteqq;":              {'\u2AC6', '\u0338'},
-	"nvap;":                    {'\u224D', '\u20D2'},
-	"nvge;":                    {'\u2265', '\u20D2'},
-	"nvgt;":                    {'\u003E', '\u20D2'},
-	"nvle;":                    {'\u2264', '\u20D2'},
-	"nvlt;":                    {'\u003C', '\u20D2'},
-	"nvltrie;":                 {'\u22B4', '\u20D2'},
-	"nvrtrie;":                 {'\u22B5', '\u20D2'},
-	"nvsim;":                   {'\u223C', '\u20D2'},
-	"race;":                    {'\u223D', '\u0331'},
-	"smtes;":                   {'\u2AAC', '\uFE00'},
-	"sqcaps;":                  {'\u2293', '\uFE00'},
-	"sqcups;":                  {'\u2294', '\uFE00'},
-	"varsubsetneq;":            {'\u228A', '\uFE00'},
-	"varsubsetneqq;":           {'\u2ACB', '\uFE00'},
-	"varsupsetneq;":            {'\u228B', '\uFE00'},
-	"varsupsetneqq;":           {'\u2ACC', '\uFE00'},
-	"vnsub;":                   {'\u2282', '\u20D2'},
-	"vnsup;":                   {'\u2283', '\u20D2'},
-	"vsubnE;":                  {'\u2ACB', '\uFE00'},
-	"vsubne;":                  {'\u228A', '\uFE00'},
-	"vsupnE;":                  {'\u2ACC', '\uFE00'},
-	"vsupne;":                  {'\u228B', '\uFE00'},
+var entity2 map[string][2]rune
+
+// populateMapsOnce guards calling populateMaps.
+var populateMapsOnce sync.Once
+
+// populateMaps populates entity and entity2.
+func populateMaps() {
+	entity = map[string]rune{
+		"AElig;":                           '\U000000C6',
+		"AMP;":                             '\U00000026',
+		"Aacute;":                          '\U000000C1',
+		"Abreve;":                          '\U00000102',
+		"Acirc;":                           '\U000000C2',
+		"Acy;":                             '\U00000410',
+		"Afr;":                             '\U0001D504',
+		"Agrave;":                          '\U000000C0',
+		"Alpha;":                           '\U00000391',
+		"Amacr;":                           '\U00000100',
+		"And;":                             '\U00002A53',
+		"Aogon;":                           '\U00000104',
+		"Aopf;":                            '\U0001D538',
+		"ApplyFunction;":                   '\U00002061',
+		"Aring;":                           '\U000000C5',
+		"Ascr;":                            '\U0001D49C',
+		"Assign;":                          '\U00002254',
+		"Atilde;":                          '\U000000C3',
+		"Auml;":                            '\U000000C4',
+		"Backslash;":                       '\U00002216',
+		"Barv;":                            '\U00002AE7',
+		"Barwed;":                          '\U00002306',
+		"Bcy;":                             '\U00000411',
+		"Because;":                         '\U00002235',
+		"Bernoullis;":                      '\U0000212C',
+		"Beta;":                            '\U00000392',
+		"Bfr;":                             '\U0001D505',
+		"Bopf;":                            '\U0001D539',
+		"Breve;":                           '\U000002D8',
+		"Bscr;":                            '\U0000212C',
+		"Bumpeq;":                          '\U0000224E',
+		"CHcy;":                            '\U00000427',
+		"COPY;":                            '\U000000A9',
+		"Cacute;":                          '\U00000106',
+		"Cap;":                             '\U000022D2',
+		"CapitalDifferentialD;":            '\U00002145',
+		"Cayleys;":                         '\U0000212D',
+		"Ccaron;":                          '\U0000010C',
+		"Ccedil;":                          '\U000000C7',
+		"Ccirc;":                           '\U00000108',
+		"Cconint;":                         '\U00002230',
+		"Cdot;":                            '\U0000010A',
+		"Cedilla;":                         '\U000000B8',
+		"CenterDot;":                       '\U000000B7',
+		"Cfr;":                             '\U0000212D',
+		"Chi;":                             '\U000003A7',
+		"CircleDot;":                       '\U00002299',
+		"CircleMinus;":                     '\U00002296',
+		"CirclePlus;":                      '\U00002295',
+		"CircleTimes;":                     '\U00002297',
+		"ClockwiseContourIntegral;":        '\U00002232',
+		"CloseCurlyDoubleQuote;":           '\U0000201D',
+		"CloseCurlyQuote;":                 '\U00002019',
+		"Colon;":                           '\U00002237',
+		"Colone;":                          '\U00002A74',
+		"Congruent;":                       '\U00002261',
+		"Conint;":                          '\U0000222F',
+		"ContourIntegral;":                 '\U0000222E',
+		"Copf;":                            '\U00002102',
+		"Coproduct;":                       '\U00002210',
+		"CounterClockwiseContourIntegral;": '\U00002233',
+		"Cross;":                           '\U00002A2F',
+		"Cscr;":                            '\U0001D49E',
+		"Cup;":                             '\U000022D3',
+		"CupCap;":                          '\U0000224D',
+		"DD;":                              '\U00002145',
+		"DDotrahd;":                        '\U00002911',
+		"DJcy;":                            '\U00000402',
+		"DScy;":                            '\U00000405',
+		"DZcy;":                            '\U0000040F',
+		"Dagger;":                          '\U00002021',
+		"Darr;":                            '\U000021A1',
+		"Dashv;":                           '\U00002AE4',
+		"Dcaron;":                          '\U0000010E',
+		"Dcy;":                             '\U00000414',
+		"Del;":                             '\U00002207',
+		"Delta;":                           '\U00000394',
+		"Dfr;":                             '\U0001D507',
+		"DiacriticalAcute;":                '\U000000B4',
+		"DiacriticalDot;":                  '\U000002D9',
+		"DiacriticalDoubleAcute;":          '\U000002DD',
+		"DiacriticalGrave;":                '\U00000060',
+		"DiacriticalTilde;":                '\U000002DC',
+		"Diamond;":                         '\U000022C4',
+		"DifferentialD;":                   '\U00002146',
+		"Dopf;":                            '\U0001D53B',
+		"Dot;":                             '\U000000A8',
+		"DotDot;":                          '\U000020DC',
+		"DotEqual;":                        '\U00002250',
+		"DoubleContourIntegral;":           '\U0000222F',
+		"DoubleDot;":                       '\U000000A8',
+		"DoubleDownArrow;":                 '\U000021D3',
+		"DoubleLeftArrow;":                 '\U000021D0',
+		"DoubleLeftRightArrow;":            '\U000021D4',
+		"DoubleLeftTee;":                   '\U00002AE4',
+		"DoubleLongLeftArrow;":             '\U000027F8',
+		"DoubleLongLeftRightArrow;":        '\U000027FA',
+		"DoubleLongRightArrow;":            '\U000027F9',
+		"DoubleRightArrow;":                '\U000021D2',
+		"DoubleRightTee;":                  '\U000022A8',
+		"DoubleUpArrow;":                   '\U000021D1',
+		"DoubleUpDownArrow;":               '\U000021D5',
+		"DoubleVerticalBar;":               '\U00002225',
+		"DownArrow;":                       '\U00002193',
+		"DownArrowBar;":                    '\U00002913',
+		"DownArrowUpArrow;":                '\U000021F5',
+		"DownBreve;":                       '\U00000311',
+		"DownLeftRightVector;":             '\U00002950',
+		"DownLeftTeeVector;":               '\U0000295E',
+		"DownLeftVector;":                  '\U000021BD',
+		"DownLeftVectorBar;":               '\U00002956',
+		"DownRightTeeVector;":              '\U0000295F',
+		"DownRightVector;":                 '\U000021C1',
+		"DownRightVectorBar;":              '\U00002957',
+		"DownTee;":                         '\U000022A4',
+		"DownTeeArrow;":                    '\U000021A7',
+		"Downarrow;":                       '\U000021D3',
+		"Dscr;":                            '\U0001D49F',
+		"Dstrok;":                          '\U00000110',
+		"ENG;":                             '\U0000014A',
+		"ETH;":                             '\U000000D0',
+		"Eacute;":                          '\U000000C9',
+		"Ecaron;":                          '\U0000011A',
+		"Ecirc;":                           '\U000000CA',
+		"Ecy;":                             '\U0000042D',
+		"Edot;":                            '\U00000116',
+		"Efr;":                             '\U0001D508',
+		"Egrave;":                          '\U000000C8',
+		"Element;":                         '\U00002208',
+		"Emacr;":                           '\U00000112',
+		"EmptySmallSquare;":                '\U000025FB',
+		"EmptyVerySmallSquare;":            '\U000025AB',
+		"Eogon;":                           '\U00000118',
+		"Eopf;":                            '\U0001D53C',
+		"Epsilon;":                         '\U00000395',
+		"Equal;":                           '\U00002A75',
+		"EqualTilde;":                      '\U00002242',
+		"Equilibrium;":                     '\U000021CC',
+		"Escr;":                            '\U00002130',
+		"Esim;":                            '\U00002A73',
+		"Eta;":                             '\U00000397',
+		"Euml;":                            '\U000000CB',
+		"Exists;":                          '\U00002203',
+		"ExponentialE;":                    '\U00002147',
+		"Fcy;":                             '\U00000424',
+		"Ffr;":                             '\U0001D509',
+		"FilledSmallSquare;":               '\U000025FC',
+		"FilledVerySmallSquare;":           '\U000025AA',
+		"Fopf;":                            '\U0001D53D',
+		"ForAll;":                          '\U00002200',
+		"Fouriertrf;":                      '\U00002131',
+		"Fscr;":                            '\U00002131',
+		"GJcy;":                            '\U00000403',
+		"GT;":                              '\U0000003E',
+		"Gamma;":                           '\U00000393',
+		"Gammad;":                          '\U000003DC',
+		"Gbreve;":                          '\U0000011E',
+		"Gcedil;":                          '\U00000122',
+		"Gcirc;":                           '\U0000011C',
+		"Gcy;":                             '\U00000413',
+		"Gdot;":                            '\U00000120',
+		"Gfr;":                             '\U0001D50A',
+		"Gg;":                              '\U000022D9',
+		"Gopf;":                            '\U0001D53E',
+		"GreaterEqual;":                    '\U00002265',
+		"GreaterEqualLess;":                '\U000022DB',
+		"GreaterFullEqual;":                '\U00002267',
+		"GreaterGreater;":                  '\U00002AA2',
+		"GreaterLess;":                     '\U00002277',
+		"GreaterSlantEqual;":               '\U00002A7E',
+		"GreaterTilde;":                    '\U00002273',
+		"Gscr;":                            '\U0001D4A2',
+		"Gt;":                              '\U0000226B',
+		"HARDcy;":                          '\U0000042A',
+		"Hacek;":                           '\U000002C7',
+		"Hat;":                             '\U0000005E',
+		"Hcirc;":                           '\U00000124',
+		"Hfr;":                             '\U0000210C',
+		"HilbertSpace;":                    '\U0000210B',
+		"Hopf;":                            '\U0000210D',
+		"HorizontalLine;":                  '\U00002500',
+		"Hscr;":                            '\U0000210B',
+		"Hstrok;":                          '\U00000126',
+		"HumpDownHump;":                    '\U0000224E',
+		"HumpEqual;":                       '\U0000224F',
+		"IEcy;":                            '\U00000415',
+		"IJlig;":                           '\U00000132',
+		"IOcy;":                            '\U00000401',
+		"Iacute;":                          '\U000000CD',
+		"Icirc;":                           '\U000000CE',
+		"Icy;":                             '\U00000418',
+		"Idot;":                            '\U00000130',
+		"Ifr;":                             '\U00002111',
+		"Igrave;":                          '\U000000CC',
+		"Im;":                              '\U00002111',
+		"Imacr;":                           '\U0000012A',
+		"ImaginaryI;":                      '\U00002148',
+		"Implies;":                         '\U000021D2',
+		"Int;":                             '\U0000222C',
+		"Integral;":                        '\U0000222B',
+		"Intersection;":                    '\U000022C2',
+		"InvisibleComma;":                  '\U00002063',
+		"InvisibleTimes;":                  '\U00002062',
+		"Iogon;":                           '\U0000012E',
+		"Iopf;":                            '\U0001D540',
+		"Iota;":                            '\U00000399',
+		"Iscr;":                            '\U00002110',
+		"Itilde;":                          '\U00000128',
+		"Iukcy;":                           '\U00000406',
+		"Iuml;":                            '\U000000CF',
+		"Jcirc;":                           '\U00000134',
+		"Jcy;":                             '\U00000419',
+		"Jfr;":                             '\U0001D50D',
+		"Jopf;":                            '\U0001D541',
+		"Jscr;":                            '\U0001D4A5',
+		"Jsercy;":                          '\U00000408',
+		"Jukcy;":                           '\U00000404',
+		"KHcy;":                            '\U00000425',
+		"KJcy;":                            '\U0000040C',
+		"Kappa;":                           '\U0000039A',
+		"Kcedil;":                          '\U00000136',
+		"Kcy;":                             '\U0000041A',
+		"Kfr;":                             '\U0001D50E',
+		"Kopf;":                            '\U0001D542',
+		"Kscr;":                            '\U0001D4A6',
+		"LJcy;":                            '\U00000409',
+		"LT;":                              '\U0000003C',
+		"Lacute;":                          '\U00000139',
+		"Lambda;":                          '\U0000039B',
+		"Lang;":                            '\U000027EA',
+		"Laplacetrf;":                      '\U00002112',
+		"Larr;":                            '\U0000219E',
+		"Lcaron;":                          '\U0000013D',
+		"Lcedil;":                          '\U0000013B',
+		"Lcy;":                             '\U0000041B',
+		"LeftAngleBracket;":                '\U000027E8',
+		"LeftArrow;":                       '\U00002190',
+		"LeftArrowBar;":                    '\U000021E4',
+		"LeftArrowRightArrow;":             '\U000021C6',
+		"LeftCeiling;":                     '\U00002308',
+		"LeftDoubleBracket;":               '\U000027E6',
+		"LeftDownTeeVector;":               '\U00002961',
+		"LeftDownVector;":                  '\U000021C3',
+		"LeftDownVectorBar;":               '\U00002959',
+		"LeftFloor;":                       '\U0000230A',
+		"LeftRightArrow;":                  '\U00002194',
+		"LeftRightVector;":                 '\U0000294E',
+		"LeftTee;":                         '\U000022A3',
+		"LeftTeeArrow;":                    '\U000021A4',
+		"LeftTeeVector;":                   '\U0000295A',
+		"LeftTriangle;":                    '\U000022B2',
+		"LeftTriangleBar;":                 '\U000029CF',
+		"LeftTriangleEqual;":               '\U000022B4',
+		"LeftUpDownVector;":                '\U00002951',
+		"LeftUpTeeVector;":                 '\U00002960',
+		"LeftUpVector;":                    '\U000021BF',
+		"LeftUpVectorBar;":                 '\U00002958',
+		"LeftVector;":                      '\U000021BC',
+		"LeftVectorBar;":                   '\U00002952',
+		"Leftarrow;":                       '\U000021D0',
+		"Leftrightarrow;":                  '\U000021D4',
+		"LessEqualGreater;":                '\U000022DA',
+		"LessFullEqual;":                   '\U00002266',
+		"LessGreater;":                     '\U00002276',
+		"LessLess;":                        '\U00002AA1',
+		"LessSlantEqual;":                  '\U00002A7D',
+		"LessTilde;":                       '\U00002272',
+		"Lfr;":                             '\U0001D50F',
+		"Ll;":                              '\U000022D8',
+		"Lleftarrow;":                      '\U000021DA',
+		"Lmidot;":                          '\U0000013F',
+		"LongLeftArrow;":                   '\U000027F5',
+		"LongLeftRightArrow;":              '\U000027F7',
+		"LongRightArrow;":                  '\U000027F6',
+		"Longleftarrow;":                   '\U000027F8',
+		"Longleftrightarrow;":              '\U000027FA',
+		"Longrightarrow;":                  '\U000027F9',
+		"Lopf;":                            '\U0001D543',
+		"LowerLeftArrow;":                  '\U00002199',
+		"LowerRightArrow;":                 '\U00002198',
+		"Lscr;":                            '\U00002112',
+		"Lsh;":                             '\U000021B0',
+		"Lstrok;":                          '\U00000141',
+		"Lt;":                              '\U0000226A',
+		"Map;":                             '\U00002905',
+		"Mcy;":                             '\U0000041C',
+		"MediumSpace;":                     '\U0000205F',
+		"Mellintrf;":                       '\U00002133',
+		"Mfr;":                             '\U0001D510',
+		"MinusPlus;":                       '\U00002213',
+		"Mopf;":                            '\U0001D544',
+		"Mscr;":                            '\U00002133',
+		"Mu;":                              '\U0000039C',
+		"NJcy;":                            '\U0000040A',
+		"Nacute;":                          '\U00000143',
+		"Ncaron;":                          '\U00000147',
+		"Ncedil;":                          '\U00000145',
+		"Ncy;":                             '\U0000041D',
+		"NegativeMediumSpace;":             '\U0000200B',
+		"NegativeThickSpace;":              '\U0000200B',
+		"NegativeThinSpace;":               '\U0000200B',
+		"NegativeVeryThinSpace;":           '\U0000200B',
+		"NestedGreaterGreater;":            '\U0000226B',
+		"NestedLessLess;":                  '\U0000226A',
+		"NewLine;":                         '\U0000000A',
+		"Nfr;":                             '\U0001D511',
+		"NoBreak;":                         '\U00002060',
+		"NonBreakingSpace;":                '\U000000A0',
+		"Nopf;":                            '\U00002115',
+		"Not;":                             '\U00002AEC',
+		"NotCongruent;":                    '\U00002262',
+		"NotCupCap;":                       '\U0000226D',
+		"NotDoubleVerticalBar;":            '\U00002226',
+		"NotElement;":                      '\U00002209',
+		"NotEqual;":                        '\U00002260',
+		"NotExists;":                       '\U00002204',
+		"NotGreater;":                      '\U0000226F',
+		"NotGreaterEqual;":                 '\U00002271',
+		"NotGreaterLess;":                  '\U00002279',
+		"NotGreaterTilde;":                 '\U00002275',
+		"NotLeftTriangle;":                 '\U000022EA',
+		"NotLeftTriangleEqual;":            '\U000022EC',
+		"NotLess;":                         '\U0000226E',
+		"NotLessEqual;":                    '\U00002270',
+		"NotLessGreater;":                  '\U00002278',
+		"NotLessTilde;":                    '\U00002274',
+		"NotPrecedes;":                     '\U00002280',
+		"NotPrecedesSlantEqual;":           '\U000022E0',
+		"NotReverseElement;":               '\U0000220C',
+		"NotRightTriangle;":                '\U000022EB',
+		"NotRightTriangleEqual;":           '\U000022ED',
+		"NotSquareSubsetEqual;":            '\U000022E2',
+		"NotSquareSupersetEqual;":          '\U000022E3',
+		"NotSubsetEqual;":                  '\U00002288',
+		"NotSucceeds;":                     '\U00002281',
+		"NotSucceedsSlantEqual;":           '\U000022E1',
+		"NotSupersetEqual;":                '\U00002289',
+		"NotTilde;":                        '\U00002241',
+		"NotTildeEqual;":                   '\U00002244',
+		"NotTildeFullEqual;":               '\U00002247',
+		"NotTildeTilde;":                   '\U00002249',
+		"NotVerticalBar;":                  '\U00002224',
+		"Nscr;":                            '\U0001D4A9',
+		"Ntilde;":                          '\U000000D1',
+		"Nu;":                              '\U0000039D',
+		"OElig;":                           '\U00000152',
+		"Oacute;":                          '\U000000D3',
+		"Ocirc;":                           '\U000000D4',
+		"Ocy;":                             '\U0000041E',
+		"Odblac;":                          '\U00000150',
+		"Ofr;":                             '\U0001D512',
+		"Ograve;":                          '\U000000D2',
+		"Omacr;":                           '\U0000014C',
+		"Omega;":                           '\U000003A9',
+		"Omicron;":                         '\U0000039F',
+		"Oopf;":                            '\U0001D546',
+		"OpenCurlyDoubleQuote;":            '\U0000201C',
+		"OpenCurlyQuote;":                  '\U00002018',
+		"Or;":                              '\U00002A54',
+		"Oscr;":                            '\U0001D4AA',
+		"Oslash;":                          '\U000000D8',
+		"Otilde;":                          '\U000000D5',
+		"Otimes;":                          '\U00002A37',
+		"Ouml;":                            '\U000000D6',
+		"OverBar;":                         '\U0000203E',
+		"OverBrace;":                       '\U000023DE',
+		"OverBracket;":                     '\U000023B4',
+		"OverParenthesis;":                 '\U000023DC',
+		"PartialD;":                        '\U00002202',
+		"Pcy;":                             '\U0000041F',
+		"Pfr;":                             '\U0001D513',
+		"Phi;":                             '\U000003A6',
+		"Pi;":                              '\U000003A0',
+		"PlusMinus;":                       '\U000000B1',
+		"Poincareplane;":                   '\U0000210C',
+		"Popf;":                            '\U00002119',
+		"Pr;":                              '\U00002ABB',
+		"Precedes;":                        '\U0000227A',
+		"PrecedesEqual;":                   '\U00002AAF',
+		"PrecedesSlantEqual;":              '\U0000227C',
+		"PrecedesTilde;":                   '\U0000227E',
+		"Prime;":                           '\U00002033',
+		"Product;":                         '\U0000220F',
+		"Proportion;":                      '\U00002237',
+		"Proportional;":                    '\U0000221D',
+		"Pscr;":                            '\U0001D4AB',
+		"Psi;":                             '\U000003A8',
+		"QUOT;":                            '\U00000022',
+		"Qfr;":                             '\U0001D514',
+		"Qopf;":                            '\U0000211A',
+		"Qscr;":                            '\U0001D4AC',
+		"RBarr;":                           '\U00002910',
+		"REG;":                             '\U000000AE',
+		"Racute;":                          '\U00000154',
+		"Rang;":                            '\U000027EB',
+		"Rarr;":                            '\U000021A0',
+		"Rarrtl;":                          '\U00002916',
+		"Rcaron;":                          '\U00000158',
+		"Rcedil;":                          '\U00000156',
+		"Rcy;":                             '\U00000420',
+		"Re;":                              '\U0000211C',
+		"ReverseElement;":                  '\U0000220B',
+		"ReverseEquilibrium;":              '\U000021CB',
+		"ReverseUpEquilibrium;":            '\U0000296F',
+		"Rfr;":                             '\U0000211C',
+		"Rho;":                             '\U000003A1',
+		"RightAngleBracket;":               '\U000027E9',
+		"RightArrow;":                      '\U00002192',
+		"RightArrowBar;":                   '\U000021E5',
+		"RightArrowLeftArrow;":             '\U000021C4',
+		"RightCeiling;":                    '\U00002309',
+		"RightDoubleBracket;":              '\U000027E7',
+		"RightDownTeeVector;":              '\U0000295D',
+		"RightDownVector;":                 '\U000021C2',
+		"RightDownVectorBar;":              '\U00002955',
+		"RightFloor;":                      '\U0000230B',
+		"RightTee;":                        '\U000022A2',
+		"RightTeeArrow;":                   '\U000021A6',
+		"RightTeeVector;":                  '\U0000295B',
+		"RightTriangle;":                   '\U000022B3',
+		"RightTriangleBar;":                '\U000029D0',
+		"RightTriangleEqual;":              '\U000022B5',
+		"RightUpDownVector;":               '\U0000294F',
+		"RightUpTeeVector;":                '\U0000295C',
+		"RightUpVector;":                   '\U000021BE',
+		"RightUpVectorBar;":                '\U00002954',
+		"RightVector;":                     '\U000021C0',
+		"RightVectorBar;":                  '\U00002953',
+		"Rightarrow;":                      '\U000021D2',
+		"Ropf;":                            '\U0000211D',
+		"RoundImplies;":                    '\U00002970',
+		"Rrightarrow;":                     '\U000021DB',
+		"Rscr;":                            '\U0000211B',
+		"Rsh;":                             '\U000021B1',
+		"RuleDelayed;":                     '\U000029F4',
+		"SHCHcy;":                          '\U00000429',
+		"SHcy;":                            '\U00000428',
+		"SOFTcy;":                          '\U0000042C',
+		"Sacute;":                          '\U0000015A',
+		"Sc;":                              '\U00002ABC',
+		"Scaron;":                          '\U00000160',
+		"Scedil;":                          '\U0000015E',
+		"Scirc;":                           '\U0000015C',
+		"Scy;":                             '\U00000421',
+		"Sfr;":                             '\U0001D516',
+		"ShortDownArrow;":                  '\U00002193',
+		"ShortLeftArrow;":                  '\U00002190',
+		"ShortRightArrow;":                 '\U00002192',
+		"ShortUpArrow;":                    '\U00002191',
+		"Sigma;":                           '\U000003A3',
+		"SmallCircle;":                     '\U00002218',
+		"Sopf;":                            '\U0001D54A',
+		"Sqrt;":                            '\U0000221A',
+		"Square;":                          '\U000025A1',
+		"SquareIntersection;":              '\U00002293',
+		"SquareSubset;":                    '\U0000228F',
+		"SquareSubsetEqual;":               '\U00002291',
+		"SquareSuperset;":                  '\U00002290',
+		"SquareSupersetEqual;":             '\U00002292',
+		"SquareUnion;":                     '\U00002294',
+		"Sscr;":                            '\U0001D4AE',
+		"Star;":                            '\U000022C6',
+		"Sub;":                             '\U000022D0',
+		"Subset;":                          '\U000022D0',
+		"SubsetEqual;":                     '\U00002286',
+		"Succeeds;":                        '\U0000227B',
+		"SucceedsEqual;":                   '\U00002AB0',
+		"SucceedsSlantEqual;":              '\U0000227D',
+		"SucceedsTilde;":                   '\U0000227F',
+		"SuchThat;":                        '\U0000220B',
+		"Sum;":                             '\U00002211',
+		"Sup;":                             '\U000022D1',
+		"Superset;":                        '\U00002283',
+		"SupersetEqual;":                   '\U00002287',
+		"Supset;":                          '\U000022D1',
+		"THORN;":                           '\U000000DE',
+		"TRADE;":                           '\U00002122',
+		"TSHcy;":                           '\U0000040B',
+		"TScy;":                            '\U00000426',
+		"Tab;":                             '\U00000009',
+		"Tau;":                             '\U000003A4',
+		"Tcaron;":                          '\U00000164',
+		"Tcedil;":                          '\U00000162',
+		"Tcy;":                             '\U00000422',
+		"Tfr;":                             '\U0001D517',
+		"Therefore;":                       '\U00002234',
+		"Theta;":                           '\U00000398',
+		"ThinSpace;":                       '\U00002009',
+		"Tilde;":                           '\U0000223C',
+		"TildeEqual;":                      '\U00002243',
+		"TildeFullEqual;":                  '\U00002245',
+		"TildeTilde;":                      '\U00002248',
+		"Topf;":                            '\U0001D54B',
+		"TripleDot;":                       '\U000020DB',
+		"Tscr;":                            '\U0001D4AF',
+		"Tstrok;":                          '\U00000166',
+		"Uacute;":                          '\U000000DA',
+		"Uarr;":                            '\U0000219F',
+		"Uarrocir;":                        '\U00002949',
+		"Ubrcy;":                           '\U0000040E',
+		"Ubreve;":                          '\U0000016C',
+		"Ucirc;":                           '\U000000DB',
+		"Ucy;":                             '\U00000423',
+		"Udblac;":                          '\U00000170',
+		"Ufr;":                             '\U0001D518',
+		"Ugrave;":                          '\U000000D9',
+		"Umacr;":                           '\U0000016A',
+		"UnderBar;":                        '\U0000005F',
+		"UnderBrace;":                      '\U000023DF',
+		"UnderBracket;":                    '\U000023B5',
+		"UnderParenthesis;":                '\U000023DD',
+		"Union;":                           '\U000022C3',
+		"UnionPlus;":                       '\U0000228E',
+		"Uogon;":                           '\U00000172',
+		"Uopf;":                            '\U0001D54C',
+		"UpArrow;":                         '\U00002191',
+		"UpArrowBar;":                      '\U00002912',
+		"UpArrowDownArrow;":                '\U000021C5',
+		"UpDownArrow;":                     '\U00002195',
+		"UpEquilibrium;":                   '\U0000296E',
+		"UpTee;":                           '\U000022A5',
+		"UpTeeArrow;":                      '\U000021A5',
+		"Uparrow;":                         '\U000021D1',
+		"Updownarrow;":                     '\U000021D5',
+		"UpperLeftArrow;":                  '\U00002196',
+		"UpperRightArrow;":                 '\U00002197',
+		"Upsi;":                            '\U000003D2',
+		"Upsilon;":                         '\U000003A5',
+		"Uring;":                           '\U0000016E',
+		"Uscr;":                            '\U0001D4B0',
+		"Utilde;":                          '\U00000168',
+		"Uuml;":                            '\U000000DC',
+		"VDash;":                           '\U000022AB',
+		"Vbar;":                            '\U00002AEB',
+		"Vcy;":                             '\U00000412',
+		"Vdash;":                           '\U000022A9',
+		"Vdashl;":                          '\U00002AE6',
+		"Vee;":                             '\U000022C1',
+		"Verbar;":                          '\U00002016',
+		"Vert;":                            '\U00002016',
+		"VerticalBar;":                     '\U00002223',
+		"VerticalLine;":                    '\U0000007C',
+		"VerticalSeparator;":               '\U00002758',
+		"VerticalTilde;":                   '\U00002240',
+		"VeryThinSpace;":                   '\U0000200A',
+		"Vfr;":                             '\U0001D519',
+		"Vopf;":                            '\U0001D54D',
+		"Vscr;":                            '\U0001D4B1',
+		"Vvdash;":                          '\U000022AA',
+		"Wcirc;":                           '\U00000174',
+		"Wedge;":                           '\U000022C0',
+		"Wfr;":                             '\U0001D51A',
+		"Wopf;":                            '\U0001D54E',
+		"Wscr;":                            '\U0001D4B2',
+		"Xfr;":                             '\U0001D51B',
+		"Xi;":                              '\U0000039E',
+		"Xopf;":                            '\U0001D54F',
+		"Xscr;":                            '\U0001D4B3',
+		"YAcy;":                            '\U0000042F',
+		"YIcy;":                            '\U00000407',
+		"YUcy;":                            '\U0000042E',
+		"Yacute;":                          '\U000000DD',
+		"Ycirc;":                           '\U00000176',
+		"Ycy;":                             '\U0000042B',
+		"Yfr;":                             '\U0001D51C',
+		"Yopf;":                            '\U0001D550',
+		"Yscr;":                            '\U0001D4B4',
+		"Yuml;":                            '\U00000178',
+		"ZHcy;":                            '\U00000416',
+		"Zacute;":                          '\U00000179',
+		"Zcaron;":                          '\U0000017D',
+		"Zcy;":                             '\U00000417',
+		"Zdot;":                            '\U0000017B',
+		"ZeroWidthSpace;":                  '\U0000200B',
+		"Zeta;":                            '\U00000396',
+		"Zfr;":                             '\U00002128',
+		"Zopf;":                            '\U00002124',
+		"Zscr;":                            '\U0001D4B5',
+		"aacute;":                          '\U000000E1',
+		"abreve;":                          '\U00000103',
+		"ac;":                              '\U0000223E',
+		"acd;":                             '\U0000223F',
+		"acirc;":                           '\U000000E2',
+		"acute;":                           '\U000000B4',
+		"acy;":                             '\U00000430',
+		"aelig;":                           '\U000000E6',
+		"af;":                              '\U00002061',
+		"afr;":                             '\U0001D51E',
+		"agrave;":                          '\U000000E0',
+		"alefsym;":                         '\U00002135',
+		"aleph;":                           '\U00002135',
+		"alpha;":                           '\U000003B1',
+		"amacr;":                           '\U00000101',
+		"amalg;":                           '\U00002A3F',
+		"amp;":                             '\U00000026',
+		"and;":                             '\U00002227',
+		"andand;":                          '\U00002A55',
+		"andd;":                            '\U00002A5C',
+		"andslope;":                        '\U00002A58',
+		"andv;":                            '\U00002A5A',
+		"ang;":                             '\U00002220',
+		"ange;":                            '\U000029A4',
+		"angle;":                           '\U00002220',
+		"angmsd;":                          '\U00002221',
+		"angmsdaa;":                        '\U000029A8',
+		"angmsdab;":                        '\U000029A9',
+		"angmsdac;":                        '\U000029AA',
+		"angmsdad;":                        '\U000029AB',
+		"angmsdae;":                        '\U000029AC',
+		"angmsdaf;":                        '\U000029AD',
+		"angmsdag;":                        '\U000029AE',
+		"angmsdah;":                        '\U000029AF',
+		"angrt;":                           '\U0000221F',
+		"angrtvb;":                         '\U000022BE',
+		"angrtvbd;":                        '\U0000299D',
+		"angsph;":                          '\U00002222',
+		"angst;":                           '\U000000C5',
+		"angzarr;":                         '\U0000237C',
+		"aogon;":                           '\U00000105',
+		"aopf;":                            '\U0001D552',
+		"ap;":                              '\U00002248',
+		"apE;":                             '\U00002A70',
+		"apacir;":                          '\U00002A6F',
+		"ape;":                             '\U0000224A',
+		"apid;":                            '\U0000224B',
+		"apos;":                            '\U00000027',
+		"approx;":                          '\U00002248',
+		"approxeq;":                        '\U0000224A',
+		"aring;":                           '\U000000E5',
+		"ascr;":                            '\U0001D4B6',
+		"ast;":                             '\U0000002A',
+		"asymp;":                           '\U00002248',
+		"asympeq;":                         '\U0000224D',
+		"atilde;":                          '\U000000E3',
+		"auml;":                            '\U000000E4',
+		"awconint;":                        '\U00002233',
+		"awint;":                           '\U00002A11',
+		"bNot;":                            '\U00002AED',
+		"backcong;":                        '\U0000224C',
+		"backepsilon;":                     '\U000003F6',
+		"backprime;":                       '\U00002035',
+		"backsim;":                         '\U0000223D',
+		"backsimeq;":                       '\U000022CD',
+		"barvee;":                          '\U000022BD',
+		"barwed;":                          '\U00002305',
+		"barwedge;":                        '\U00002305',
+		"bbrk;":                            '\U000023B5',
+		"bbrktbrk;":                        '\U000023B6',
+		"bcong;":                           '\U0000224C',
+		"bcy;":                             '\U00000431',
+		"bdquo;":                           '\U0000201E',
+		"becaus;":                          '\U00002235',
+		"because;":                         '\U00002235',
+		"bemptyv;":                         '\U000029B0',
+		"bepsi;":                           '\U000003F6',
+		"bernou;":                          '\U0000212C',
+		"beta;":                            '\U000003B2',
+		"beth;":                            '\U00002136',
+		"between;":                         '\U0000226C',
+		"bfr;":                             '\U0001D51F',
+		"bigcap;":                          '\U000022C2',
+		"bigcirc;":                         '\U000025EF',
+		"bigcup;":                          '\U000022C3',
+		"bigodot;":                         '\U00002A00',
+		"bigoplus;":                        '\U00002A01',
+		"bigotimes;":                       '\U00002A02',
+		"bigsqcup;":                        '\U00002A06',
+		"bigstar;":                         '\U00002605',
+		"bigtriangledown;":                 '\U000025BD',
+		"bigtriangleup;":                   '\U000025B3',
+		"biguplus;":                        '\U00002A04',
+		"bigvee;":                          '\U000022C1',
+		"bigwedge;":                        '\U000022C0',
+		"bkarow;":                          '\U0000290D',
+		"blacklozenge;":                    '\U000029EB',
+		"blacksquare;":                     '\U000025AA',
+		"blacktriangle;":                   '\U000025B4',
+		"blacktriangledown;":               '\U000025BE',
+		"blacktriangleleft;":               '\U000025C2',
+		"blacktriangleright;":              '\U000025B8',
+		"blank;":                           '\U00002423',
+		"blk12;":                           '\U00002592',
+		"blk14;":                           '\U00002591',
+		"blk34;":                           '\U00002593',
+		"block;":                           '\U00002588',
+		"bnot;":                            '\U00002310',
+		"bopf;":                            '\U0001D553',
+		"bot;":                             '\U000022A5',
+		"bottom;":                          '\U000022A5',
+		"bowtie;":                          '\U000022C8',
+		"boxDL;":                           '\U00002557',
+		"boxDR;":                           '\U00002554',
+		"boxDl;":                           '\U00002556',
+		"boxDr;":                           '\U00002553',
+		"boxH;":                            '\U00002550',
+		"boxHD;":                           '\U00002566',
+		"boxHU;":                           '\U00002569',
+		"boxHd;":                           '\U00002564',
+		"boxHu;":                           '\U00002567',
+		"boxUL;":                           '\U0000255D',
+		"boxUR;":                           '\U0000255A',
+		"boxUl;":                           '\U0000255C',
+		"boxUr;":                           '\U00002559',
+		"boxV;":                            '\U00002551',
+		"boxVH;":                           '\U0000256C',
+		"boxVL;":                           '\U00002563',
+		"boxVR;":                           '\U00002560',
+		"boxVh;":                           '\U0000256B',
+		"boxVl;":                           '\U00002562',
+		"boxVr;":                           '\U0000255F',
+		"boxbox;":                          '\U000029C9',
+		"boxdL;":                           '\U00002555',
+		"boxdR;":                           '\U00002552',
+		"boxdl;":                           '\U00002510',
+		"boxdr;":                           '\U0000250C',
+		"boxh;":                            '\U00002500',
+		"boxhD;":                           '\U00002565',
+		"boxhU;":                           '\U00002568',
+		"boxhd;":                           '\U0000252C',
+		"boxhu;":                           '\U00002534',
+		"boxminus;":                        '\U0000229F',
+		"boxplus;":                         '\U0000229E',
+		"boxtimes;":                        '\U000022A0',
+		"boxuL;":                           '\U0000255B',
+		"boxuR;":                           '\U00002558',
+		"boxul;":                           '\U00002518',
+		"boxur;":                           '\U00002514',
+		"boxv;":                            '\U00002502',
+		"boxvH;":                           '\U0000256A',
+		"boxvL;":                           '\U00002561',
+		"boxvR;":                           '\U0000255E',
+		"boxvh;":                           '\U0000253C',
+		"boxvl;":                           '\U00002524',
+		"boxvr;":                           '\U0000251C',
+		"bprime;":                          '\U00002035',
+		"breve;":                           '\U000002D8',
+		"brvbar;":                          '\U000000A6',
+		"bscr;":                            '\U0001D4B7',
+		"bsemi;":                           '\U0000204F',
+		"bsim;":                            '\U0000223D',
+		"bsime;":                           '\U000022CD',
+		"bsol;":                            '\U0000005C',
+		"bsolb;":                           '\U000029C5',
+		"bsolhsub;":                        '\U000027C8',
+		"bull;":                            '\U00002022',
+		"bullet;":                          '\U00002022',
+		"bump;":                            '\U0000224E',
+		"bumpE;":                           '\U00002AAE',
+		"bumpe;":                           '\U0000224F',
+		"bumpeq;":                          '\U0000224F',
+		"cacute;":                          '\U00000107',
+		"cap;":                             '\U00002229',
+		"capand;":                          '\U00002A44',
+		"capbrcup;":                        '\U00002A49',
+		"capcap;":                          '\U00002A4B',
+		"capcup;":                          '\U00002A47',
+		"capdot;":                          '\U00002A40',
+		"caret;":                           '\U00002041',
+		"caron;":                           '\U000002C7',
+		"ccaps;":                           '\U00002A4D',
+		"ccaron;":                          '\U0000010D',
+		"ccedil;":                          '\U000000E7',
+		"ccirc;":                           '\U00000109',
+		"ccups;":                           '\U00002A4C',
+		"ccupssm;":                         '\U00002A50',
+		"cdot;":                            '\U0000010B',
+		"cedil;":                           '\U000000B8',
+		"cemptyv;":                         '\U000029B2',
+		"cent;":                            '\U000000A2',
+		"centerdot;":                       '\U000000B7',
+		"cfr;":                             '\U0001D520',
+		"chcy;":                            '\U00000447',
+		"check;":                           '\U00002713',
+		"checkmark;":                       '\U00002713',
+		"chi;":                             '\U000003C7',
+		"cir;":                             '\U000025CB',
+		"cirE;":                            '\U000029C3',
+		"circ;":                            '\U000002C6',
+		"circeq;":                          '\U00002257',
+		"circlearrowleft;":                 '\U000021BA',
+		"circlearrowright;":                '\U000021BB',
+		"circledR;":                        '\U000000AE',
+		"circledS;":                        '\U000024C8',
+		"circledast;":                      '\U0000229B',
+		"circledcirc;":                     '\U0000229A',
+		"circleddash;":                     '\U0000229D',
+		"cire;":                            '\U00002257',
+		"cirfnint;":                        '\U00002A10',
+		"cirmid;":                          '\U00002AEF',
+		"cirscir;":                         '\U000029C2',
+		"clubs;":                           '\U00002663',
+		"clubsuit;":                        '\U00002663',
+		"colon;":                           '\U0000003A',
+		"colone;":                          '\U00002254',
+		"coloneq;":                         '\U00002254',
+		"comma;":                           '\U0000002C',
+		"commat;":                          '\U00000040',
+		"comp;":                            '\U00002201',
+		"compfn;":                          '\U00002218',
+		"complement;":                      '\U00002201',
+		"complexes;":                       '\U00002102',
+		"cong;":                            '\U00002245',
+		"congdot;":                         '\U00002A6D',
+		"conint;":                          '\U0000222E',
+		"copf;":                            '\U0001D554',
+		"coprod;":                          '\U00002210',
+		"copy;":                            '\U000000A9',
+		"copysr;":                          '\U00002117',
+		"crarr;":                           '\U000021B5',
+		"cross;":                           '\U00002717',
+		"cscr;":                            '\U0001D4B8',
+		"csub;":                            '\U00002ACF',
+		"csube;":                           '\U00002AD1',
+		"csup;":                            '\U00002AD0',
+		"csupe;":                           '\U00002AD2',
+		"ctdot;":                           '\U000022EF',
+		"cudarrl;":                         '\U00002938',
+		"cudarrr;":                         '\U00002935',
+		"cuepr;":                           '\U000022DE',
+		"cuesc;":                           '\U000022DF',
+		"cularr;":                          '\U000021B6',
+		"cularrp;":                         '\U0000293D',
+		"cup;":                             '\U0000222A',
+		"cupbrcap;":                        '\U00002A48',
+		"cupcap;":                          '\U00002A46',
+		"cupcup;":                          '\U00002A4A',
+		"cupdot;":                          '\U0000228D',
+		"cupor;":                           '\U00002A45',
+		"curarr;":                          '\U000021B7',
+		"curarrm;":                         '\U0000293C',
+		"curlyeqprec;":                     '\U000022DE',
+		"curlyeqsucc;":                     '\U000022DF',
+		"curlyvee;":                        '\U000022CE',
+		"curlywedge;":                      '\U000022CF',
+		"curren;":                          '\U000000A4',
+		"curvearrowleft;":                  '\U000021B6',
+		"curvearrowright;":                 '\U000021B7',
+		"cuvee;":                           '\U000022CE',
+		"cuwed;":                           '\U000022CF',
+		"cwconint;":                        '\U00002232',
+		"cwint;":                           '\U00002231',
+		"cylcty;":                          '\U0000232D',
+		"dArr;":                            '\U000021D3',
+		"dHar;":                            '\U00002965',
+		"dagger;":                          '\U00002020',
+		"daleth;":                          '\U00002138',
+		"darr;":                            '\U00002193',
+		"dash;":                            '\U00002010',
+		"dashv;":                           '\U000022A3',
+		"dbkarow;":                         '\U0000290F',
+		"dblac;":                           '\U000002DD',
+		"dcaron;":                          '\U0000010F',
+		"dcy;":                             '\U00000434',
+		"dd;":                              '\U00002146',
+		"ddagger;":                         '\U00002021',
+		"ddarr;":                           '\U000021CA',
+		"ddotseq;":                         '\U00002A77',
+		"deg;":                             '\U000000B0',
+		"delta;":                           '\U000003B4',
+		"demptyv;":                         '\U000029B1',
+		"dfisht;":                          '\U0000297F',
+		"dfr;":                             '\U0001D521',
+		"dharl;":                           '\U000021C3',
+		"dharr;":                           '\U000021C2',
+		"diam;":                            '\U000022C4',
+		"diamond;":                         '\U000022C4',
+		"diamondsuit;":                     '\U00002666',
+		"diams;":                           '\U00002666',
+		"die;":                             '\U000000A8',
+		"digamma;":                         '\U000003DD',
+		"disin;":                           '\U000022F2',
+		"div;":                             '\U000000F7',
+		"divide;":                          '\U000000F7',
+		"divideontimes;":                   '\U000022C7',
+		"divonx;":                          '\U000022C7',
+		"djcy;":                            '\U00000452',
+		"dlcorn;":                          '\U0000231E',
+		"dlcrop;":                          '\U0000230D',
+		"dollar;":                          '\U00000024',
+		"dopf;":                            '\U0001D555',
+		"dot;":                             '\U000002D9',
+		"doteq;":                           '\U00002250',
+		"doteqdot;":                        '\U00002251',
+		"dotminus;":                        '\U00002238',
+		"dotplus;":                         '\U00002214',
+		"dotsquare;":                       '\U000022A1',
+		"doublebarwedge;":                  '\U00002306',
+		"downarrow;":                       '\U00002193',
+		"downdownarrows;":                  '\U000021CA',
+		"downharpoonleft;":                 '\U000021C3',
+		"downharpoonright;":                '\U000021C2',
+		"drbkarow;":                        '\U00002910',
+		"drcorn;":                          '\U0000231F',
+		"drcrop;":                          '\U0000230C',
+		"dscr;":                            '\U0001D4B9',
+		"dscy;":                            '\U00000455',
+		"dsol;":                            '\U000029F6',
+		"dstrok;":                          '\U00000111',
+		"dtdot;":                           '\U000022F1',
+		"dtri;":                            '\U000025BF',
+		"dtrif;":                           '\U000025BE',
+		"duarr;":                           '\U000021F5',
+		"duhar;":                           '\U0000296F',
+		"dwangle;":                         '\U000029A6',
+		"dzcy;":                            '\U0000045F',
+		"dzigrarr;":                        '\U000027FF',
+		"eDDot;":                           '\U00002A77',
+		"eDot;":                            '\U00002251',
+		"eacute;":                          '\U000000E9',
+		"easter;":                          '\U00002A6E',
+		"ecaron;":                          '\U0000011B',
+		"ecir;":                            '\U00002256',
+		"ecirc;":                           '\U000000EA',
+		"ecolon;":                          '\U00002255',
+		"ecy;":                             '\U0000044D',
+		"edot;":                            '\U00000117',
+		"ee;":                              '\U00002147',
+		"efDot;":                           '\U00002252',
+		"efr;":                             '\U0001D522',
+		"eg;":                              '\U00002A9A',
+		"egrave;":                          '\U000000E8',
+		"egs;":                             '\U00002A96',
+		"egsdot;":                          '\U00002A98',
+		"el;":                              '\U00002A99',
+		"elinters;":                        '\U000023E7',
+		"ell;":                             '\U00002113',
+		"els;":                             '\U00002A95',
+		"elsdot;":                          '\U00002A97',
+		"emacr;":                           '\U00000113',
+		"empty;":                           '\U00002205',
+		"emptyset;":                        '\U00002205',
+		"emptyv;":                          '\U00002205',
+		"emsp;":                            '\U00002003',
+		"emsp13;":                          '\U00002004',
+		"emsp14;":                          '\U00002005',
+		"eng;":                             '\U0000014B',
+		"ensp;":                            '\U00002002',
+		"eogon;":                           '\U00000119',
+		"eopf;":                            '\U0001D556',
+		"epar;":                            '\U000022D5',
+		"eparsl;":                          '\U000029E3',
+		"eplus;":                           '\U00002A71',
+		"epsi;":                            '\U000003B5',
+		"epsilon;":                         '\U000003B5',
+		"epsiv;":                           '\U000003F5',
+		"eqcirc;":                          '\U00002256',
+		"eqcolon;":                         '\U00002255',
+		"eqsim;":                           '\U00002242',
+		"eqslantgtr;":                      '\U00002A96',
+		"eqslantless;":                     '\U00002A95',
+		"equals;":                          '\U0000003D',
+		"equest;":                          '\U0000225F',
+		"equiv;":                           '\U00002261',
+		"equivDD;":                         '\U00002A78',
+		"eqvparsl;":                        '\U000029E5',
+		"erDot;":                           '\U00002253',
+		"erarr;":                           '\U00002971',
+		"escr;":                            '\U0000212F',
+		"esdot;":                           '\U00002250',
+		"esim;":                            '\U00002242',
+		"eta;":                             '\U000003B7',
+		"eth;":                             '\U000000F0',
+		"euml;":                            '\U000000EB',
+		"euro;":                            '\U000020AC',
+		"excl;":                            '\U00000021',
+		"exist;":                           '\U00002203',
+		"expectation;":                     '\U00002130',
+		"exponentiale;":                    '\U00002147',
+		"fallingdotseq;":                   '\U00002252',
+		"fcy;":                             '\U00000444',
+		"female;":                          '\U00002640',
+		"ffilig;":                          '\U0000FB03',
+		"fflig;":                           '\U0000FB00',
+		"ffllig;":                          '\U0000FB04',
+		"ffr;":                             '\U0001D523',
+		"filig;":                           '\U0000FB01',
+		"flat;":                            '\U0000266D',
+		"fllig;":                           '\U0000FB02',
+		"fltns;":                           '\U000025B1',
+		"fnof;":                            '\U00000192',
+		"fopf;":                            '\U0001D557',
+		"forall;":                          '\U00002200',
+		"fork;":                            '\U000022D4',
+		"forkv;":                           '\U00002AD9',
+		"fpartint;":                        '\U00002A0D',
+		"frac12;":                          '\U000000BD',
+		"frac13;":                          '\U00002153',
+		"frac14;":                          '\U000000BC',
+		"frac15;":                          '\U00002155',
+		"frac16;":                          '\U00002159',
+		"frac18;":                          '\U0000215B',
+		"frac23;":                          '\U00002154',
+		"frac25;":                          '\U00002156',
+		"frac34;":                          '\U000000BE',
+		"frac35;":                          '\U00002157',
+		"frac38;":                          '\U0000215C',
+		"frac45;":                          '\U00002158',
+		"frac56;":                          '\U0000215A',
+		"frac58;":                          '\U0000215D',
+		"frac78;":                          '\U0000215E',
+		"frasl;":                           '\U00002044',
+		"frown;":                           '\U00002322',
+		"fscr;":                            '\U0001D4BB',
+		"gE;":                              '\U00002267',
+		"gEl;":                             '\U00002A8C',
+		"gacute;":                          '\U000001F5',
+		"gamma;":                           '\U000003B3',
+		"gammad;":                          '\U000003DD',
+		"gap;":                             '\U00002A86',
+		"gbreve;":                          '\U0000011F',
+		"gcirc;":                           '\U0000011D',
+		"gcy;":                             '\U00000433',
+		"gdot;":                            '\U00000121',
+		"ge;":                              '\U00002265',
+		"gel;":                             '\U000022DB',
+		"geq;":                             '\U00002265',
+		"geqq;":                            '\U00002267',
+		"geqslant;":                        '\U00002A7E',
+		"ges;":                             '\U00002A7E',
+		"gescc;":                           '\U00002AA9',
+		"gesdot;":                          '\U00002A80',
+		"gesdoto;":                         '\U00002A82',
+		"gesdotol;":                        '\U00002A84',
+		"gesles;":                          '\U00002A94',
+		"gfr;":                             '\U0001D524',
+		"gg;":                              '\U0000226B',
+		"ggg;":                             '\U000022D9',
+		"gimel;":                           '\U00002137',
+		"gjcy;":                            '\U00000453',
+		"gl;":                              '\U00002277',
+		"glE;":                             '\U00002A92',
+		"gla;":                             '\U00002AA5',
+		"glj;":                             '\U00002AA4',
+		"gnE;":                             '\U00002269',
+		"gnap;":                            '\U00002A8A',
+		"gnapprox;":                        '\U00002A8A',
+		"gne;":                             '\U00002A88',
+		"gneq;":                            '\U00002A88',
+		"gneqq;":                           '\U00002269',
+		"gnsim;":                           '\U000022E7',
+		"gopf;":                            '\U0001D558',
+		"grave;":                           '\U00000060',
+		"gscr;":                            '\U0000210A',
+		"gsim;":                            '\U00002273',
+		"gsime;":                           '\U00002A8E',
+		"gsiml;":                           '\U00002A90',
+		"gt;":                              '\U0000003E',
+		"gtcc;":                            '\U00002AA7',
+		"gtcir;":                           '\U00002A7A',
+		"gtdot;":                           '\U000022D7',
+		"gtlPar;":                          '\U00002995',
+		"gtquest;":                         '\U00002A7C',
+		"gtrapprox;":                       '\U00002A86',
+		"gtrarr;":                          '\U00002978',
+		"gtrdot;":                          '\U000022D7',
+		"gtreqless;":                       '\U000022DB',
+		"gtreqqless;":                      '\U00002A8C',
+		"gtrless;":                         '\U00002277',
+		"gtrsim;":                          '\U00002273',
+		"hArr;":                            '\U000021D4',
+		"hairsp;":                          '\U0000200A',
+		"half;":                            '\U000000BD',
+		"hamilt;":                          '\U0000210B',
+		"hardcy;":                          '\U0000044A',
+		"harr;":                            '\U00002194',
+		"harrcir;":                         '\U00002948',
+		"harrw;":                           '\U000021AD',
+		"hbar;":                            '\U0000210F',
+		"hcirc;":                           '\U00000125',
+		"hearts;":                          '\U00002665',
+		"heartsuit;":                       '\U00002665',
+		"hellip;":                          '\U00002026',
+		"hercon;":                          '\U000022B9',
+		"hfr;":                             '\U0001D525',
+		"hksearow;":                        '\U00002925',
+		"hkswarow;":                        '\U00002926',
+		"hoarr;":                           '\U000021FF',
+		"homtht;":                          '\U0000223B',
+		"hookleftarrow;":                   '\U000021A9',
+		"hookrightarrow;":                  '\U000021AA',
+		"hopf;":                            '\U0001D559',
+		"horbar;":                          '\U00002015',
+		"hscr;":                            '\U0001D4BD',
+		"hslash;":                          '\U0000210F',
+		"hstrok;":                          '\U00000127',
+		"hybull;":                          '\U00002043',
+		"hyphen;":                          '\U00002010',
+		"iacute;":                          '\U000000ED',
+		"ic;":                              '\U00002063',
+		"icirc;":                           '\U000000EE',
+		"icy;":                             '\U00000438',
+		"iecy;":                            '\U00000435',
+		"iexcl;":                           '\U000000A1',
+		"iff;":                             '\U000021D4',
+		"ifr;":                             '\U0001D526',
+		"igrave;":                          '\U000000EC',
+		"ii;":                              '\U00002148',
+		"iiiint;":                          '\U00002A0C',
+		"iiint;":                           '\U0000222D',
+		"iinfin;":                          '\U000029DC',
+		"iiota;":                           '\U00002129',
+		"ijlig;":                           '\U00000133',
+		"imacr;":                           '\U0000012B',
+		"image;":                           '\U00002111',
+		"imagline;":                        '\U00002110',
+		"imagpart;":                        '\U00002111',
+		"imath;":                           '\U00000131',
+		"imof;":                            '\U000022B7',
+		"imped;":                           '\U000001B5',
+		"in;":                              '\U00002208',
+		"incare;":                          '\U00002105',
+		"infin;":                           '\U0000221E',
+		"infintie;":                        '\U000029DD',
+		"inodot;":                          '\U00000131',
+		"int;":                             '\U0000222B',
+		"intcal;":                          '\U000022BA',
+		"integers;":                        '\U00002124',
+		"intercal;":                        '\U000022BA',
+		"intlarhk;":                        '\U00002A17',
+		"intprod;":                         '\U00002A3C',
+		"iocy;":                            '\U00000451',
+		"iogon;":                           '\U0000012F',
+		"iopf;":                            '\U0001D55A',
+		"iota;":                            '\U000003B9',
+		"iprod;":                           '\U00002A3C',
+		"iquest;":                          '\U000000BF',
+		"iscr;":                            '\U0001D4BE',
+		"isin;":                            '\U00002208',
+		"isinE;":                           '\U000022F9',
+		"isindot;":                         '\U000022F5',
+		"isins;":                           '\U000022F4',
+		"isinsv;":                          '\U000022F3',
+		"isinv;":                           '\U00002208',
+		"it;":                              '\U00002062',
+		"itilde;":                          '\U00000129',
+		"iukcy;":                           '\U00000456',
+		"iuml;":                            '\U000000EF',
+		"jcirc;":                           '\U00000135',
+		"jcy;":                             '\U00000439',
+		"jfr;":                             '\U0001D527',
+		"jmath;":                           '\U00000237',
+		"jopf;":                            '\U0001D55B',
+		"jscr;":                            '\U0001D4BF',
+		"jsercy;":                          '\U00000458',
+		"jukcy;":                           '\U00000454',
+		"kappa;":                           '\U000003BA',
+		"kappav;":                          '\U000003F0',
+		"kcedil;":                          '\U00000137',
+		"kcy;":                             '\U0000043A',
+		"kfr;":                             '\U0001D528',
+		"kgreen;":                          '\U00000138',
+		"khcy;":                            '\U00000445',
+		"kjcy;":                            '\U0000045C',
+		"kopf;":                            '\U0001D55C',
+		"kscr;":                            '\U0001D4C0',
+		"lAarr;":                           '\U000021DA',
+		"lArr;":                            '\U000021D0',
+		"lAtail;":                          '\U0000291B',
+		"lBarr;":                           '\U0000290E',
+		"lE;":                              '\U00002266',
+		"lEg;":                             '\U00002A8B',
+		"lHar;":                            '\U00002962',
+		"lacute;":                          '\U0000013A',
+		"laemptyv;":                        '\U000029B4',
+		"lagran;":                          '\U00002112',
+		"lambda;":                          '\U000003BB',
+		"lang;":                            '\U000027E8',
+		"langd;":                           '\U00002991',
+		"langle;":                          '\U000027E8',
+		"lap;":                             '\U00002A85',
+		"laquo;":                           '\U000000AB',
+		"larr;":                            '\U00002190',
+		"larrb;":                           '\U000021E4',
+		"larrbfs;":                         '\U0000291F',
+		"larrfs;":                          '\U0000291D',
+		"larrhk;":                          '\U000021A9',
+		"larrlp;":                          '\U000021AB',
+		"larrpl;":                          '\U00002939',
+		"larrsim;":                         '\U00002973',
+		"larrtl;":                          '\U000021A2',
+		"lat;":                             '\U00002AAB',
+		"latail;":                          '\U00002919',
+		"late;":                            '\U00002AAD',
+		"lbarr;":                           '\U0000290C',
+		"lbbrk;":                           '\U00002772',
+		"lbrace;":                          '\U0000007B',
+		"lbrack;":                          '\U0000005B',
+		"lbrke;":                           '\U0000298B',
+		"lbrksld;":                         '\U0000298F',
+		"lbrkslu;":                         '\U0000298D',
+		"lcaron;":                          '\U0000013E',
+		"lcedil;":                          '\U0000013C',
+		"lceil;":                           '\U00002308',
+		"lcub;":                            '\U0000007B',
+		"lcy;":                             '\U0000043B',
+		"ldca;":                            '\U00002936',
+		"ldquo;":                           '\U0000201C',
+		"ldquor;":                          '\U0000201E',
+		"ldrdhar;":                         '\U00002967',
+		"ldrushar;":                        '\U0000294B',
+		"ldsh;":                            '\U000021B2',
+		"le;":                              '\U00002264',
+		"leftarrow;":                       '\U00002190',
+		"leftarrowtail;":                   '\U000021A2',
+		"leftharpoondown;":                 '\U000021BD',
+		"leftharpoonup;":                   '\U000021BC',
+		"leftleftarrows;":                  '\U000021C7',
+		"leftrightarrow;":                  '\U00002194',
+		"leftrightarrows;":                 '\U000021C6',
+		"leftrightharpoons;":               '\U000021CB',
+		"leftrightsquigarrow;":             '\U000021AD',
+		"leftthreetimes;":                  '\U000022CB',
+		"leg;":                             '\U000022DA',
+		"leq;":                             '\U00002264',
+		"leqq;":                            '\U00002266',
+		"leqslant;":                        '\U00002A7D',
+		"les;":                             '\U00002A7D',
+		"lescc;":                           '\U00002AA8',
+		"lesdot;":                          '\U00002A7F',
+		"lesdoto;":                         '\U00002A81',
+		"lesdotor;":                        '\U00002A83',
+		"lesges;":                          '\U00002A93',
+		"lessapprox;":                      '\U00002A85',
+		"lessdot;":                         '\U000022D6',
+		"lesseqgtr;":                       '\U000022DA',
+		"lesseqqgtr;":                      '\U00002A8B',
+		"lessgtr;":                         '\U00002276',
+		"lesssim;":                         '\U00002272',
+		"lfisht;":                          '\U0000297C',
+		"lfloor;":                          '\U0000230A',
+		"lfr;":                             '\U0001D529',
+		"lg;":                              '\U00002276',
+		"lgE;":                             '\U00002A91',
+		"lhard;":                           '\U000021BD',
+		"lharu;":                           '\U000021BC',
+		"lharul;":                          '\U0000296A',
+		"lhblk;":                           '\U00002584',
+		"ljcy;":                            '\U00000459',
+		"ll;":                              '\U0000226A',
+		"llarr;":                           '\U000021C7',
+		"llcorner;":                        '\U0000231E',
+		"llhard;":                          '\U0000296B',
+		"lltri;":                           '\U000025FA',
+		"lmidot;":                          '\U00000140',
+		"lmoust;":                          '\U000023B0',
+		"lmoustache;":                      '\U000023B0',
+		"lnE;":                             '\U00002268',
+		"lnap;":                            '\U00002A89',
+		"lnapprox;":                        '\U00002A89',
+		"lne;":                             '\U00002A87',
+		"lneq;":                            '\U00002A87',
+		"lneqq;":                           '\U00002268',
+		"lnsim;":                           '\U000022E6',
+		"loang;":                           '\U000027EC',
+		"loarr;":                           '\U000021FD',
+		"lobrk;":                           '\U000027E6',
+		"longleftarrow;":                   '\U000027F5',
+		"longleftrightarrow;":              '\U000027F7',
+		"longmapsto;":                      '\U000027FC',
+		"longrightarrow;":                  '\U000027F6',
+		"looparrowleft;":                   '\U000021AB',
+		"looparrowright;":                  '\U000021AC',
+		"lopar;":                           '\U00002985',
+		"lopf;":                            '\U0001D55D',
+		"loplus;":                          '\U00002A2D',
+		"lotimes;":                         '\U00002A34',
+		"lowast;":                          '\U00002217',
+		"lowbar;":                          '\U0000005F',
+		"loz;":                             '\U000025CA',
+		"lozenge;":                         '\U000025CA',
+		"lozf;":                            '\U000029EB',
+		"lpar;":                            '\U00000028',
+		"lparlt;":                          '\U00002993',
+		"lrarr;":                           '\U000021C6',
+		"lrcorner;":                        '\U0000231F',
+		"lrhar;":                           '\U000021CB',
+		"lrhard;":                          '\U0000296D',
+		"lrm;":                             '\U0000200E',
+		"lrtri;":                           '\U000022BF',
+		"lsaquo;":                          '\U00002039',
+		"lscr;":                            '\U0001D4C1',
+		"lsh;":                             '\U000021B0',
+		"lsim;":                            '\U00002272',
+		"lsime;":                           '\U00002A8D',
+		"lsimg;":                           '\U00002A8F',
+		"lsqb;":                            '\U0000005B',
+		"lsquo;":                           '\U00002018',
+		"lsquor;":                          '\U0000201A',
+		"lstrok;":                          '\U00000142',
+		"lt;":                              '\U0000003C',
+		"ltcc;":                            '\U00002AA6',
+		"ltcir;":                           '\U00002A79',
+		"ltdot;":                           '\U000022D6',
+		"lthree;":                          '\U000022CB',
+		"ltimes;":                          '\U000022C9',
+		"ltlarr;":                          '\U00002976',
+		"ltquest;":                         '\U00002A7B',
+		"ltrPar;":                          '\U00002996',
+		"ltri;":                            '\U000025C3',
+		"ltrie;":                           '\U000022B4',
+		"ltrif;":                           '\U000025C2',
+		"lurdshar;":                        '\U0000294A',
+		"luruhar;":                         '\U00002966',
+		"mDDot;":                           '\U0000223A',
+		"macr;":                            '\U000000AF',
+		"male;":                            '\U00002642',
+		"malt;":                            '\U00002720',
+		"maltese;":                         '\U00002720',
+		"map;":                             '\U000021A6',
+		"mapsto;":                          '\U000021A6',
+		"mapstodown;":                      '\U000021A7',
+		"mapstoleft;":                      '\U000021A4',
+		"mapstoup;":                        '\U000021A5',
+		"marker;":                          '\U000025AE',
+		"mcomma;":                          '\U00002A29',
+		"mcy;":                             '\U0000043C',
+		"mdash;":                           '\U00002014',
+		"measuredangle;":                   '\U00002221',
+		"mfr;":                             '\U0001D52A',
+		"mho;":                             '\U00002127',
+		"micro;":                           '\U000000B5',
+		"mid;":                             '\U00002223',
+		"midast;":                          '\U0000002A',
+		"midcir;":                          '\U00002AF0',
+		"middot;":                          '\U000000B7',
+		"minus;":                           '\U00002212',
+		"minusb;":                          '\U0000229F',
+		"minusd;":                          '\U00002238',
+		"minusdu;":                         '\U00002A2A',
+		"mlcp;":                            '\U00002ADB',
+		"mldr;":                            '\U00002026',
+		"mnplus;":                          '\U00002213',
+		"models;":                          '\U000022A7',
+		"mopf;":                            '\U0001D55E',
+		"mp;":                              '\U00002213',
+		"mscr;":                            '\U0001D4C2',
+		"mstpos;":                          '\U0000223E',
+		"mu;":                              '\U000003BC',
+		"multimap;":                        '\U000022B8',
+		"mumap;":                           '\U000022B8',
+		"nLeftarrow;":                      '\U000021CD',
+		"nLeftrightarrow;":                 '\U000021CE',
+		"nRightarrow;":                     '\U000021CF',
+		"nVDash;":                          '\U000022AF',
+		"nVdash;":                          '\U000022AE',
+		"nabla;":                           '\U00002207',
+		"nacute;":                          '\U00000144',
+		"nap;":                             '\U00002249',
+		"napos;":                           '\U00000149',
+		"napprox;":                         '\U00002249',
+		"natur;":                           '\U0000266E',
+		"natural;":                         '\U0000266E',
+		"naturals;":                        '\U00002115',
+		"nbsp;":                            '\U000000A0',
+		"ncap;":                            '\U00002A43',
+		"ncaron;":                          '\U00000148',
+		"ncedil;":                          '\U00000146',
+		"ncong;":                           '\U00002247',
+		"ncup;":                            '\U00002A42',
+		"ncy;":                             '\U0000043D',
+		"ndash;":                           '\U00002013',
+		"ne;":                              '\U00002260',
+		"neArr;":                           '\U000021D7',
+		"nearhk;":                          '\U00002924',
+		"nearr;":                           '\U00002197',
+		"nearrow;":                         '\U00002197',
+		"nequiv;":                          '\U00002262',
+		"nesear;":                          '\U00002928',
+		"nexist;":                          '\U00002204',
+		"nexists;":                         '\U00002204',
+		"nfr;":                             '\U0001D52B',
+		"nge;":                             '\U00002271',
+		"ngeq;":                            '\U00002271',
+		"ngsim;":                           '\U00002275',
+		"ngt;":                             '\U0000226F',
+		"ngtr;":                            '\U0000226F',
+		"nhArr;":                           '\U000021CE',
+		"nharr;":                           '\U000021AE',
+		"nhpar;":                           '\U00002AF2',
+		"ni;":                              '\U0000220B',
+		"nis;":                             '\U000022FC',
+		"nisd;":                            '\U000022FA',
+		"niv;":                             '\U0000220B',
+		"njcy;":                            '\U0000045A',
+		"nlArr;":                           '\U000021CD',
+		"nlarr;":                           '\U0000219A',
+		"nldr;":                            '\U00002025',
+		"nle;":                             '\U00002270',
+		"nleftarrow;":                      '\U0000219A',
+		"nleftrightarrow;":                 '\U000021AE',
+		"nleq;":                            '\U00002270',
+		"nless;":                           '\U0000226E',
+		"nlsim;":                           '\U00002274',
+		"nlt;":                             '\U0000226E',
+		"nltri;":                           '\U000022EA',
+		"nltrie;":                          '\U000022EC',
+		"nmid;":                            '\U00002224',
+		"nopf;":                            '\U0001D55F',
+		"not;":                             '\U000000AC',
+		"notin;":                           '\U00002209',
+		"notinva;":                         '\U00002209',
+		"notinvb;":                         '\U000022F7',
+		"notinvc;":                         '\U000022F6',
+		"notni;":                           '\U0000220C',
+		"notniva;":                         '\U0000220C',
+		"notnivb;":                         '\U000022FE',
+		"notnivc;":                         '\U000022FD',
+		"npar;":                            '\U00002226',
+		"nparallel;":                       '\U00002226',
+		"npolint;":                         '\U00002A14',
+		"npr;":                             '\U00002280',
+		"nprcue;":                          '\U000022E0',
+		"nprec;":                           '\U00002280',
+		"nrArr;":                           '\U000021CF',
+		"nrarr;":                           '\U0000219B',
+		"nrightarrow;":                     '\U0000219B',
+		"nrtri;":                           '\U000022EB',
+		"nrtrie;":                          '\U000022ED',
+		"nsc;":                             '\U00002281',
+		"nsccue;":                          '\U000022E1',
+		"nscr;":                            '\U0001D4C3',
+		"nshortmid;":                       '\U00002224',
+		"nshortparallel;":                  '\U00002226',
+		"nsim;":                            '\U00002241',
+		"nsime;":                           '\U00002244',
+		"nsimeq;":                          '\U00002244',
+		"nsmid;":                           '\U00002224',
+		"nspar;":                           '\U00002226',
+		"nsqsube;":                         '\U000022E2',
+		"nsqsupe;":                         '\U000022E3',
+		"nsub;":                            '\U00002284',
+		"nsube;":                           '\U00002288',
+		"nsubseteq;":                       '\U00002288',
+		"nsucc;":                           '\U00002281',
+		"nsup;":                            '\U00002285',
+		"nsupe;":                           '\U00002289',
+		"nsupseteq;":                       '\U00002289',
+		"ntgl;":                            '\U00002279',
+		"ntilde;":                          '\U000000F1',
+		"ntlg;":                            '\U00002278',
+		"ntriangleleft;":                   '\U000022EA',
+		"ntrianglelefteq;":                 '\U000022EC',
+		"ntriangleright;":                  '\U000022EB',
+		"ntrianglerighteq;":                '\U000022ED',
+		"nu;":                              '\U000003BD',
+		"num;":                             '\U00000023',
+		"numero;":                          '\U00002116',
+		"numsp;":                           '\U00002007',
+		"nvDash;":                          '\U000022AD',
+		"nvHarr;":                          '\U00002904',
+		"nvdash;":                          '\U000022AC',
+		"nvinfin;":                         '\U000029DE',
+		"nvlArr;":                          '\U00002902',
+		"nvrArr;":                          '\U00002903',
+		"nwArr;":                           '\U000021D6',
+		"nwarhk;":                          '\U00002923',
+		"nwarr;":                           '\U00002196',
+		"nwarrow;":                         '\U00002196',
+		"nwnear;":                          '\U00002927',
+		"oS;":                              '\U000024C8',
+		"oacute;":                          '\U000000F3',
+		"oast;":                            '\U0000229B',
+		"ocir;":                            '\U0000229A',
+		"ocirc;":                           '\U000000F4',
+		"ocy;":                             '\U0000043E',
+		"odash;":                           '\U0000229D',
+		"odblac;":                          '\U00000151',
+		"odiv;":                            '\U00002A38',
+		"odot;":                            '\U00002299',
+		"odsold;":                          '\U000029BC',
+		"oelig;":                           '\U00000153',
+		"ofcir;":                           '\U000029BF',
+		"ofr;":                             '\U0001D52C',
+		"ogon;":                            '\U000002DB',
+		"ograve;":                          '\U000000F2',
+		"ogt;":                             '\U000029C1',
+		"ohbar;":                           '\U000029B5',
+		"ohm;":                             '\U000003A9',
+		"oint;":                            '\U0000222E',
+		"olarr;":                           '\U000021BA',
+		"olcir;":                           '\U000029BE',
+		"olcross;":                         '\U000029BB',
+		"oline;":                           '\U0000203E',
+		"olt;":                             '\U000029C0',
+		"omacr;":                           '\U0000014D',
+		"omega;":                           '\U000003C9',
+		"omicron;":                         '\U000003BF',
+		"omid;":                            '\U000029B6',
+		"ominus;":                          '\U00002296',
+		"oopf;":                            '\U0001D560',
+		"opar;":                            '\U000029B7',
+		"operp;":                           '\U000029B9',
+		"oplus;":                           '\U00002295',
+		"or;":                              '\U00002228',
+		"orarr;":                           '\U000021BB',
+		"ord;":                             '\U00002A5D',
+		"order;":                           '\U00002134',
+		"orderof;":                         '\U00002134',
+		"ordf;":                            '\U000000AA',
+		"ordm;":                            '\U000000BA',
+		"origof;":                          '\U000022B6',
+		"oror;":                            '\U00002A56',
+		"orslope;":                         '\U00002A57',
+		"orv;":                             '\U00002A5B',
+		"oscr;":                            '\U00002134',
+		"oslash;":                          '\U000000F8',
+		"osol;":                            '\U00002298',
+		"otilde;":                          '\U000000F5',
+		"otimes;":                          '\U00002297',
+		"otimesas;":                        '\U00002A36',
+		"ouml;":                            '\U000000F6',
+		"ovbar;":                           '\U0000233D',
+		"par;":                             '\U00002225',
+		"para;":                            '\U000000B6',
+		"parallel;":                        '\U00002225',
+		"parsim;":                          '\U00002AF3',
+		"parsl;":                           '\U00002AFD',
+		"part;":                            '\U00002202',
+		"pcy;":                             '\U0000043F',
+		"percnt;":                          '\U00000025',
+		"period;":                          '\U0000002E',
+		"permil;":                          '\U00002030',
+		"perp;":                            '\U000022A5',
+		"pertenk;":                         '\U00002031',
+		"pfr;":                             '\U0001D52D',
+		"phi;":                             '\U000003C6',
+		"phiv;":                            '\U000003D5',
+		"phmmat;":                          '\U00002133',
+		"phone;":                           '\U0000260E',
+		"pi;":                              '\U000003C0',
+		"pitchfork;":                       '\U000022D4',
+		"piv;":                             '\U000003D6',
+		"planck;":                          '\U0000210F',
+		"planckh;":                         '\U0000210E',
+		"plankv;":                          '\U0000210F',
+		"plus;":                            '\U0000002B',
+		"plusacir;":                        '\U00002A23',
+		"plusb;":                           '\U0000229E',
+		"pluscir;":                         '\U00002A22',
+		"plusdo;":                          '\U00002214',
+		"plusdu;":                          '\U00002A25',
+		"pluse;":                           '\U00002A72',
+		"plusmn;":                          '\U000000B1',
+		"plussim;":                         '\U00002A26',
+		"plustwo;":                         '\U00002A27',
+		"pm;":                              '\U000000B1',
+		"pointint;":                        '\U00002A15',
+		"popf;":                            '\U0001D561',
+		"pound;":                           '\U000000A3',
+		"pr;":                              '\U0000227A',
+		"prE;":                             '\U00002AB3',
+		"prap;":                            '\U00002AB7',
+		"prcue;":                           '\U0000227C',
+		"pre;":                             '\U00002AAF',
+		"prec;":                            '\U0000227A',
+		"precapprox;":                      '\U00002AB7',
+		"preccurlyeq;":                     '\U0000227C',
+		"preceq;":                          '\U00002AAF',
+		"precnapprox;":                     '\U00002AB9',
+		"precneqq;":                        '\U00002AB5',
+		"precnsim;":                        '\U000022E8',
+		"precsim;":                         '\U0000227E',
+		"prime;":                           '\U00002032',
+		"primes;":                          '\U00002119',
+		"prnE;":                            '\U00002AB5',
+		"prnap;":                           '\U00002AB9',
+		"prnsim;":                          '\U000022E8',
+		"prod;":                            '\U0000220F',
+		"profalar;":                        '\U0000232E',
+		"profline;":                        '\U00002312',
+		"profsurf;":                        '\U00002313',
+		"prop;":                            '\U0000221D',
+		"propto;":                          '\U0000221D',
+		"prsim;":                           '\U0000227E',
+		"prurel;":                          '\U000022B0',
+		"pscr;":                            '\U0001D4C5',
+		"psi;":                             '\U000003C8',
+		"puncsp;":                          '\U00002008',
+		"qfr;":                             '\U0001D52E',
+		"qint;":                            '\U00002A0C',
+		"qopf;":                            '\U0001D562',
+		"qprime;":                          '\U00002057',
+		"qscr;":                            '\U0001D4C6',
+		"quaternions;":                     '\U0000210D',
+		"quatint;":                         '\U00002A16',
+		"quest;":                           '\U0000003F',
+		"questeq;":                         '\U0000225F',
+		"quot;":                            '\U00000022',
+		"rAarr;":                           '\U000021DB',
+		"rArr;":                            '\U000021D2',
+		"rAtail;":                          '\U0000291C',
+		"rBarr;":                           '\U0000290F',
+		"rHar;":                            '\U00002964',
+		"racute;":                          '\U00000155',
+		"radic;":                           '\U0000221A',
+		"raemptyv;":                        '\U000029B3',
+		"rang;":                            '\U000027E9',
+		"rangd;":                           '\U00002992',
+		"range;":                           '\U000029A5',
+		"rangle;":                          '\U000027E9',
+		"raquo;":                           '\U000000BB',
+		"rarr;":                            '\U00002192',
+		"rarrap;":                          '\U00002975',
+		"rarrb;":                           '\U000021E5',
+		"rarrbfs;":                         '\U00002920',
+		"rarrc;":                           '\U00002933',
+		"rarrfs;":                          '\U0000291E',
+		"rarrhk;":                          '\U000021AA',
+		"rarrlp;":                          '\U000021AC',
+		"rarrpl;":                          '\U00002945',
+		"rarrsim;":                         '\U00002974',
+		"rarrtl;":                          '\U000021A3',
+		"rarrw;":                           '\U0000219D',
+		"ratail;":                          '\U0000291A',
+		"ratio;":                           '\U00002236',
+		"rationals;":                       '\U0000211A',
+		"rbarr;":                           '\U0000290D',
+		"rbbrk;":                           '\U00002773',
+		"rbrace;":                          '\U0000007D',
+		"rbrack;":                          '\U0000005D',
+		"rbrke;":                           '\U0000298C',
+		"rbrksld;":                         '\U0000298E',
+		"rbrkslu;":                         '\U00002990',
+		"rcaron;":                          '\U00000159',
+		"rcedil;":                          '\U00000157',
+		"rceil;":                           '\U00002309',
+		"rcub;":                            '\U0000007D',
+		"rcy;":                             '\U00000440',
+		"rdca;":                            '\U00002937',
+		"rdldhar;":                         '\U00002969',
+		"rdquo;":                           '\U0000201D',
+		"rdquor;":                          '\U0000201D',
+		"rdsh;":                            '\U000021B3',
+		"real;":                            '\U0000211C',
+		"realine;":                         '\U0000211B',
+		"realpart;":                        '\U0000211C',
+		"reals;":                           '\U0000211D',
+		"rect;":                            '\U000025AD',
+		"reg;":                             '\U000000AE',
+		"rfisht;":                          '\U0000297D',
+		"rfloor;":                          '\U0000230B',
+		"rfr;":                             '\U0001D52F',
+		"rhard;":                           '\U000021C1',
+		"rharu;":                           '\U000021C0',
+		"rharul;":                          '\U0000296C',
+		"rho;":                             '\U000003C1',
+		"rhov;":                            '\U000003F1',
+		"rightarrow;":                      '\U00002192',
+		"rightarrowtail;":                  '\U000021A3',
+		"rightharpoondown;":                '\U000021C1',
+		"rightharpoonup;":                  '\U000021C0',
+		"rightleftarrows;":                 '\U000021C4',
+		"rightleftharpoons;":               '\U000021CC',
+		"rightrightarrows;":                '\U000021C9',
+		"rightsquigarrow;":                 '\U0000219D',
+		"rightthreetimes;":                 '\U000022CC',
+		"ring;":                            '\U000002DA',
+		"risingdotseq;":                    '\U00002253',
+		"rlarr;":                           '\U000021C4',
+		"rlhar;":                           '\U000021CC',
+		"rlm;":                             '\U0000200F',
+		"rmoust;":                          '\U000023B1',
+		"rmoustache;":                      '\U000023B1',
+		"rnmid;":                           '\U00002AEE',
+		"roang;":                           '\U000027ED',
+		"roarr;":                           '\U000021FE',
+		"robrk;":                           '\U000027E7',
+		"ropar;":                           '\U00002986',
+		"ropf;":                            '\U0001D563',
+		"roplus;":                          '\U00002A2E',
+		"rotimes;":                         '\U00002A35',
+		"rpar;":                            '\U00000029',
+		"rpargt;":                          '\U00002994',
+		"rppolint;":                        '\U00002A12',
+		"rrarr;":                           '\U000021C9',
+		"rsaquo;":                          '\U0000203A',
+		"rscr;":                            '\U0001D4C7',
+		"rsh;":                             '\U000021B1',
+		"rsqb;":                            '\U0000005D',
+		"rsquo;":                           '\U00002019',
+		"rsquor;":                          '\U00002019',
+		"rthree;":                          '\U000022CC',
+		"rtimes;":                          '\U000022CA',
+		"rtri;":                            '\U000025B9',
+		"rtrie;":                           '\U000022B5',
+		"rtrif;":                           '\U000025B8',
+		"rtriltri;":                        '\U000029CE',
+		"ruluhar;":                         '\U00002968',
+		"rx;":                              '\U0000211E',
+		"sacute;":                          '\U0000015B',
+		"sbquo;":                           '\U0000201A',
+		"sc;":                              '\U0000227B',
+		"scE;":                             '\U00002AB4',
+		"scap;":                            '\U00002AB8',
+		"scaron;":                          '\U00000161',
+		"sccue;":                           '\U0000227D',
+		"sce;":                             '\U00002AB0',
+		"scedil;":                          '\U0000015F',
+		"scirc;":                           '\U0000015D',
+		"scnE;":                            '\U00002AB6',
+		"scnap;":                           '\U00002ABA',
+		"scnsim;":                          '\U000022E9',
+		"scpolint;":                        '\U00002A13',
+		"scsim;":                           '\U0000227F',
+		"scy;":                             '\U00000441',
+		"sdot;":                            '\U000022C5',
+		"sdotb;":                           '\U000022A1',
+		"sdote;":                           '\U00002A66',
+		"seArr;":                           '\U000021D8',
+		"searhk;":                          '\U00002925',
+		"searr;":                           '\U00002198',
+		"searrow;":                         '\U00002198',
+		"sect;":                            '\U000000A7',
+		"semi;":                            '\U0000003B',
+		"seswar;":                          '\U00002929',
+		"setminus;":                        '\U00002216',
+		"setmn;":                           '\U00002216',
+		"sext;":                            '\U00002736',
+		"sfr;":                             '\U0001D530',
+		"sfrown;":                          '\U00002322',
+		"sharp;":                           '\U0000266F',
+		"shchcy;":                          '\U00000449',
+		"shcy;":                            '\U00000448',
+		"shortmid;":                        '\U00002223',
+		"shortparallel;":                   '\U00002225',
+		"shy;":                             '\U000000AD',
+		"sigma;":                           '\U000003C3',
+		"sigmaf;":                          '\U000003C2',
+		"sigmav;":                          '\U000003C2',
+		"sim;":                             '\U0000223C',
+		"simdot;":                          '\U00002A6A',
+		"sime;":                            '\U00002243',
+		"simeq;":                           '\U00002243',
+		"simg;":                            '\U00002A9E',
+		"simgE;":                           '\U00002AA0',
+		"siml;":                            '\U00002A9D',
+		"simlE;":                           '\U00002A9F',
+		"simne;":                           '\U00002246',
+		"simplus;":                         '\U00002A24',
+		"simrarr;":                         '\U00002972',
+		"slarr;":                           '\U00002190',
+		"smallsetminus;":                   '\U00002216',
+		"smashp;":                          '\U00002A33',
+		"smeparsl;":                        '\U000029E4',
+		"smid;":                            '\U00002223',
+		"smile;":                           '\U00002323',
+		"smt;":                             '\U00002AAA',
+		"smte;":                            '\U00002AAC',
+		"softcy;":                          '\U0000044C',
+		"sol;":                             '\U0000002F',
+		"solb;":                            '\U000029C4',
+		"solbar;":                          '\U0000233F',
+		"sopf;":                            '\U0001D564',
+		"spades;":                          '\U00002660',
+		"spadesuit;":                       '\U00002660',
+		"spar;":                            '\U00002225',
+		"sqcap;":                           '\U00002293',
+		"sqcup;":                           '\U00002294',
+		"sqsub;":                           '\U0000228F',
+		"sqsube;":                          '\U00002291',
+		"sqsubset;":                        '\U0000228F',
+		"sqsubseteq;":                      '\U00002291',
+		"sqsup;":                           '\U00002290',
+		"sqsupe;":                          '\U00002292',
+		"sqsupset;":                        '\U00002290',
+		"sqsupseteq;":                      '\U00002292',
+		"squ;":                             '\U000025A1',
+		"square;":                          '\U000025A1',
+		"squarf;":                          '\U000025AA',
+		"squf;":                            '\U000025AA',
+		"srarr;":                           '\U00002192',
+		"sscr;":                            '\U0001D4C8',
+		"ssetmn;":                          '\U00002216',
+		"ssmile;":                          '\U00002323',
+		"sstarf;":                          '\U000022C6',
+		"star;":                            '\U00002606',
+		"starf;":                           '\U00002605',
+		"straightepsilon;":                 '\U000003F5',
+		"straightphi;":                     '\U000003D5',
+		"strns;":                           '\U000000AF',
+		"sub;":                             '\U00002282',
+		"subE;":                            '\U00002AC5',
+		"subdot;":                          '\U00002ABD',
+		"sube;":                            '\U00002286',
+		"subedot;":                         '\U00002AC3',
+		"submult;":                         '\U00002AC1',
+		"subnE;":                           '\U00002ACB',
+		"subne;":                           '\U0000228A',
+		"subplus;":                         '\U00002ABF',
+		"subrarr;":                         '\U00002979',
+		"subset;":                          '\U00002282',
+		"subseteq;":                        '\U00002286',
+		"subseteqq;":                       '\U00002AC5',
+		"subsetneq;":                       '\U0000228A',
+		"subsetneqq;":                      '\U00002ACB',
+		"subsim;":                          '\U00002AC7',
+		"subsub;":                          '\U00002AD5',
+		"subsup;":                          '\U00002AD3',
+		"succ;":                            '\U0000227B',
+		"succapprox;":                      '\U00002AB8',
+		"succcurlyeq;":                     '\U0000227D',
+		"succeq;":                          '\U00002AB0',
+		"succnapprox;":                     '\U00002ABA',
+		"succneqq;":                        '\U00002AB6',
+		"succnsim;":                        '\U000022E9',
+		"succsim;":                         '\U0000227F',
+		"sum;":                             '\U00002211',
+		"sung;":                            '\U0000266A',
+		"sup;":                             '\U00002283',
+		"sup1;":                            '\U000000B9',
+		"sup2;":                            '\U000000B2',
+		"sup3;":                            '\U000000B3',
+		"supE;":                            '\U00002AC6',
+		"supdot;":                          '\U00002ABE',
+		"supdsub;":                         '\U00002AD8',
+		"supe;":                            '\U00002287',
+		"supedot;":                         '\U00002AC4',
+		"suphsol;":                         '\U000027C9',
+		"suphsub;":                         '\U00002AD7',
+		"suplarr;":                         '\U0000297B',
+		"supmult;":                         '\U00002AC2',
+		"supnE;":                           '\U00002ACC',
+		"supne;":                           '\U0000228B',
+		"supplus;":                         '\U00002AC0',
+		"supset;":                          '\U00002283',
+		"supseteq;":                        '\U00002287',
+		"supseteqq;":                       '\U00002AC6',
+		"supsetneq;":                       '\U0000228B',
+		"supsetneqq;":                      '\U00002ACC',
+		"supsim;":                          '\U00002AC8',
+		"supsub;":                          '\U00002AD4',
+		"supsup;":                          '\U00002AD6',
+		"swArr;":                           '\U000021D9',
+		"swarhk;":                          '\U00002926',
+		"swarr;":                           '\U00002199',
+		"swarrow;":                         '\U00002199',
+		"swnwar;":                          '\U0000292A',
+		"szlig;":                           '\U000000DF',
+		"target;":                          '\U00002316',
+		"tau;":                             '\U000003C4',
+		"tbrk;":                            '\U000023B4',
+		"tcaron;":                          '\U00000165',
+		"tcedil;":                          '\U00000163',
+		"tcy;":                             '\U00000442',
+		"tdot;":                            '\U000020DB',
+		"telrec;":                          '\U00002315',
+		"tfr;":                             '\U0001D531',
+		"there4;":                          '\U00002234',
+		"therefore;":                       '\U00002234',
+		"theta;":                           '\U000003B8',
+		"thetasym;":                        '\U000003D1',
+		"thetav;":                          '\U000003D1',
+		"thickapprox;":                     '\U00002248',
+		"thicksim;":                        '\U0000223C',
+		"thinsp;":                          '\U00002009',
+		"thkap;":                           '\U00002248',
+		"thksim;":                          '\U0000223C',
+		"thorn;":                           '\U000000FE',
+		"tilde;":                           '\U000002DC',
+		"times;":                           '\U000000D7',
+		"timesb;":                          '\U000022A0',
+		"timesbar;":                        '\U00002A31',
+		"timesd;":                          '\U00002A30',
+		"tint;":                            '\U0000222D',
+		"toea;":                            '\U00002928',
+		"top;":                             '\U000022A4',
+		"topbot;":                          '\U00002336',
+		"topcir;":                          '\U00002AF1',
+		"topf;":                            '\U0001D565',
+		"topfork;":                         '\U00002ADA',
+		"tosa;":                            '\U00002929',
+		"tprime;":                          '\U00002034',
+		"trade;":                           '\U00002122',
+		"triangle;":                        '\U000025B5',
+		"triangledown;":                    '\U000025BF',
+		"triangleleft;":                    '\U000025C3',
+		"trianglelefteq;":                  '\U000022B4',
+		"triangleq;":                       '\U0000225C',
+		"triangleright;":                   '\U000025B9',
+		"trianglerighteq;":                 '\U000022B5',
+		"tridot;":                          '\U000025EC',
+		"trie;":                            '\U0000225C',
+		"triminus;":                        '\U00002A3A',
+		"triplus;":                         '\U00002A39',
+		"trisb;":                           '\U000029CD',
+		"tritime;":                         '\U00002A3B',
+		"trpezium;":                        '\U000023E2',
+		"tscr;":                            '\U0001D4C9',
+		"tscy;":                            '\U00000446',
+		"tshcy;":                           '\U0000045B',
+		"tstrok;":                          '\U00000167',
+		"twixt;":                           '\U0000226C',
+		"twoheadleftarrow;":                '\U0000219E',
+		"twoheadrightarrow;":               '\U000021A0',
+		"uArr;":                            '\U000021D1',
+		"uHar;":                            '\U00002963',
+		"uacute;":                          '\U000000FA',
+		"uarr;":                            '\U00002191',
+		"ubrcy;":                           '\U0000045E',
+		"ubreve;":                          '\U0000016D',
+		"ucirc;":                           '\U000000FB',
+		"ucy;":                             '\U00000443',
+		"udarr;":                           '\U000021C5',
+		"udblac;":                          '\U00000171',
+		"udhar;":                           '\U0000296E',
+		"ufisht;":                          '\U0000297E',
+		"ufr;":                             '\U0001D532',
+		"ugrave;":                          '\U000000F9',
+		"uharl;":                           '\U000021BF',
+		"uharr;":                           '\U000021BE',
+		"uhblk;":                           '\U00002580',
+		"ulcorn;":                          '\U0000231C',
+		"ulcorner;":                        '\U0000231C',
+		"ulcrop;":                          '\U0000230F',
+		"ultri;":                           '\U000025F8',
+		"umacr;":                           '\U0000016B',
+		"uml;":                             '\U000000A8',
+		"uogon;":                           '\U00000173',
+		"uopf;":                            '\U0001D566',
+		"uparrow;":                         '\U00002191',
+		"updownarrow;":                     '\U00002195',
+		"upharpoonleft;":                   '\U000021BF',
+		"upharpoonright;":                  '\U000021BE',
+		"uplus;":                           '\U0000228E',
+		"upsi;":                            '\U000003C5',
+		"upsih;":                           '\U000003D2',
+		"upsilon;":                         '\U000003C5',
+		"upuparrows;":                      '\U000021C8',
+		"urcorn;":                          '\U0000231D',
+		"urcorner;":                        '\U0000231D',
+		"urcrop;":                          '\U0000230E',
+		"uring;":                           '\U0000016F',
+		"urtri;":                           '\U000025F9',
+		"uscr;":                            '\U0001D4CA',
+		"utdot;":                           '\U000022F0',
+		"utilde;":                          '\U00000169',
+		"utri;":                            '\U000025B5',
+		"utrif;":                           '\U000025B4',
+		"uuarr;":                           '\U000021C8',
+		"uuml;":                            '\U000000FC',
+		"uwangle;":                         '\U000029A7',
+		"vArr;":                            '\U000021D5',
+		"vBar;":                            '\U00002AE8',
+		"vBarv;":                           '\U00002AE9',
+		"vDash;":                           '\U000022A8',
+		"vangrt;":                          '\U0000299C',
+		"varepsilon;":                      '\U000003F5',
+		"varkappa;":                        '\U000003F0',
+		"varnothing;":                      '\U00002205',
+		"varphi;":                          '\U000003D5',
+		"varpi;":                           '\U000003D6',
+		"varpropto;":                       '\U0000221D',
+		"varr;":                            '\U00002195',
+		"varrho;":                          '\U000003F1',
+		"varsigma;":                        '\U000003C2',
+		"vartheta;":                        '\U000003D1',
+		"vartriangleleft;":                 '\U000022B2',
+		"vartriangleright;":                '\U000022B3',
+		"vcy;":                             '\U00000432',
+		"vdash;":                           '\U000022A2',
+		"vee;":                             '\U00002228',
+		"veebar;":                          '\U000022BB',
+		"veeeq;":                           '\U0000225A',
+		"vellip;":                          '\U000022EE',
+		"verbar;":                          '\U0000007C',
+		"vert;":                            '\U0000007C',
+		"vfr;":                             '\U0001D533',
+		"vltri;":                           '\U000022B2',
+		"vopf;":                            '\U0001D567',
+		"vprop;":                           '\U0000221D',
+		"vrtri;":                           '\U000022B3',
+		"vscr;":                            '\U0001D4CB',
+		"vzigzag;":                         '\U0000299A',
+		"wcirc;":                           '\U00000175',
+		"wedbar;":                          '\U00002A5F',
+		"wedge;":                           '\U00002227',
+		"wedgeq;":                          '\U00002259',
+		"weierp;":                          '\U00002118',
+		"wfr;":                             '\U0001D534',
+		"wopf;":                            '\U0001D568',
+		"wp;":                              '\U00002118',
+		"wr;":                              '\U00002240',
+		"wreath;":                          '\U00002240',
+		"wscr;":                            '\U0001D4CC',
+		"xcap;":                            '\U000022C2',
+		"xcirc;":                           '\U000025EF',
+		"xcup;":                            '\U000022C3',
+		"xdtri;":                           '\U000025BD',
+		"xfr;":                             '\U0001D535',
+		"xhArr;":                           '\U000027FA',
+		"xharr;":                           '\U000027F7',
+		"xi;":                              '\U000003BE',
+		"xlArr;":                           '\U000027F8',
+		"xlarr;":                           '\U000027F5',
+		"xmap;":                            '\U000027FC',
+		"xnis;":                            '\U000022FB',
+		"xodot;":                           '\U00002A00',
+		"xopf;":                            '\U0001D569',
+		"xoplus;":                          '\U00002A01',
+		"xotime;":                          '\U00002A02',
+		"xrArr;":                           '\U000027F9',
+		"xrarr;":                           '\U000027F6',
+		"xscr;":                            '\U0001D4CD',
+		"xsqcup;":                          '\U00002A06',
+		"xuplus;":                          '\U00002A04',
+		"xutri;":                           '\U000025B3',
+		"xvee;":                            '\U000022C1',
+		"xwedge;":                          '\U000022C0',
+		"yacute;":                          '\U000000FD',
+		"yacy;":                            '\U0000044F',
+		"ycirc;":                           '\U00000177',
+		"ycy;":                             '\U0000044B',
+		"yen;":                             '\U000000A5',
+		"yfr;":                             '\U0001D536',
+		"yicy;":                            '\U00000457',
+		"yopf;":                            '\U0001D56A',
+		"yscr;":                            '\U0001D4CE',
+		"yucy;":                            '\U0000044E',
+		"yuml;":                            '\U000000FF',
+		"zacute;":                          '\U0000017A',
+		"zcaron;":                          '\U0000017E',
+		"zcy;":                             '\U00000437',
+		"zdot;":                            '\U0000017C',
+		"zeetrf;":                          '\U00002128',
+		"zeta;":                            '\U000003B6',
+		"zfr;":                             '\U0001D537',
+		"zhcy;":                            '\U00000436',
+		"zigrarr;":                         '\U000021DD',
+		"zopf;":                            '\U0001D56B',
+		"zscr;":                            '\U0001D4CF',
+		"zwj;":                             '\U0000200D',
+		"zwnj;":                            '\U0000200C',
+		"AElig":                            '\U000000C6',
+		"AMP":                              '\U00000026',
+		"Aacute":                           '\U000000C1',
+		"Acirc":                            '\U000000C2',
+		"Agrave":                           '\U000000C0',
+		"Aring":                            '\U000000C5',
+		"Atilde":                           '\U000000C3',
+		"Auml":                             '\U000000C4',
+		"COPY":                             '\U000000A9',
+		"Ccedil":                           '\U000000C7',
+		"ETH":                              '\U000000D0',
+		"Eacute":                           '\U000000C9',
+		"Ecirc":                            '\U000000CA',
+		"Egrave":                           '\U000000C8',
+		"Euml":                             '\U000000CB',
+		"GT":                               '\U0000003E',
+		"Iacute":                           '\U000000CD',
+		"Icirc":                            '\U000000CE',
+		"Igrave":                           '\U000000CC',
+		"Iuml":                             '\U000000CF',
+		"LT":                               '\U0000003C',
+		"Ntilde":                           '\U000000D1',
+		"Oacute":                           '\U000000D3',
+		"Ocirc":                            '\U000000D4',
+		"Ograve":                           '\U000000D2',
+		"Oslash":                           '\U000000D8',
+		"Otilde":                           '\U000000D5',
+		"Ouml":                             '\U000000D6',
+		"QUOT":                             '\U00000022',
+		"REG":                              '\U000000AE',
+		"THORN":                            '\U000000DE',
+		"Uacute":                           '\U000000DA',
+		"Ucirc":                            '\U000000DB',
+		"Ugrave":                           '\U000000D9',
+		"Uuml":                             '\U000000DC',
+		"Yacute":                           '\U000000DD',
+		"aacute":                           '\U000000E1',
+		"acirc":                            '\U000000E2',
+		"acute":                            '\U000000B4',
+		"aelig":                            '\U000000E6',
+		"agrave":                           '\U000000E0',
+		"amp":                              '\U00000026',
+		"aring":                            '\U000000E5',
+		"atilde":                           '\U000000E3',
+		"auml":                             '\U000000E4',
+		"brvbar":                           '\U000000A6',
+		"ccedil":                           '\U000000E7',
+		"cedil":                            '\U000000B8',
+		"cent":                             '\U000000A2',
+		"copy":                             '\U000000A9',
+		"curren":                           '\U000000A4',
+		"deg":                              '\U000000B0',
+		"divide":                           '\U000000F7',
+		"eacute":                           '\U000000E9',
+		"ecirc":                            '\U000000EA',
+		"egrave":                           '\U000000E8',
+		"eth":                              '\U000000F0',
+		"euml":                             '\U000000EB',
+		"frac12":                           '\U000000BD',
+		"frac14":                           '\U000000BC',
+		"frac34":                           '\U000000BE',
+		"gt":                               '\U0000003E',
+		"iacute":                           '\U000000ED',
+		"icirc":                            '\U000000EE',
+		"iexcl":                            '\U000000A1',
+		"igrave":                           '\U000000EC',
+		"iquest":                           '\U000000BF',
+		"iuml":                             '\U000000EF',
+		"laquo":                            '\U000000AB',
+		"lt":                               '\U0000003C',
+		"macr":                             '\U000000AF',
+		"micro":                            '\U000000B5',
+		"middot":                           '\U000000B7',
+		"nbsp":                             '\U000000A0',
+		"not":                              '\U000000AC',
+		"ntilde":                           '\U000000F1',
+		"oacute":                           '\U000000F3',
+		"ocirc":                            '\U000000F4',
+		"ograve":                           '\U000000F2',
+		"ordf":                             '\U000000AA',
+		"ordm":                             '\U000000BA',
+		"oslash":                           '\U000000F8',
+		"otilde":                           '\U000000F5',
+		"ouml":                             '\U000000F6',
+		"para":                             '\U000000B6',
+		"plusmn":                           '\U000000B1',
+		"pound":                            '\U000000A3',
+		"quot":                             '\U00000022',
+		"raquo":                            '\U000000BB',
+		"reg":                              '\U000000AE',
+		"sect":                             '\U000000A7',
+		"shy":                              '\U000000AD',
+		"sup1":                             '\U000000B9',
+		"sup2":                             '\U000000B2',
+		"sup3":                             '\U000000B3',
+		"szlig":                            '\U000000DF',
+		"thorn":                            '\U000000FE',
+		"times":                            '\U000000D7',
+		"uacute":                           '\U000000FA',
+		"ucirc":                            '\U000000FB',
+		"ugrave":                           '\U000000F9',
+		"uml":                              '\U000000A8',
+		"uuml":                             '\U000000FC',
+		"yacute":                           '\U000000FD',
+		"yen":                              '\U000000A5',
+		"yuml":                             '\U000000FF',
+	}
+
+	entity2 = map[string][2]rune{
+		// TODO(nigeltao): Handle replacements that are wider than their names.
+		// "nLt;":                     {'\u226A', '\u20D2'},
+		// "nGt;":                     {'\u226B', '\u20D2'},
+		"NotEqualTilde;":           {'\u2242', '\u0338'},
+		"NotGreaterFullEqual;":     {'\u2267', '\u0338'},
+		"NotGreaterGreater;":       {'\u226B', '\u0338'},
+		"NotGreaterSlantEqual;":    {'\u2A7E', '\u0338'},
+		"NotHumpDownHump;":         {'\u224E', '\u0338'},
+		"NotHumpEqual;":            {'\u224F', '\u0338'},
+		"NotLeftTriangleBar;":      {'\u29CF', '\u0338'},
+		"NotLessLess;":             {'\u226A', '\u0338'},
+		"NotLessSlantEqual;":       {'\u2A7D', '\u0338'},
+		"NotNestedGreaterGreater;": {'\u2AA2', '\u0338'},
+		"NotNestedLessLess;":       {'\u2AA1', '\u0338'},
+		"NotPrecedesEqual;":        {'\u2AAF', '\u0338'},
+		"NotRightTriangleBar;":     {'\u29D0', '\u0338'},
+		"NotSquareSubset;":         {'\u228F', '\u0338'},
+		"NotSquareSuperset;":       {'\u2290', '\u0338'},
+		"NotSubset;":               {'\u2282', '\u20D2'},
+		"NotSucceedsEqual;":        {'\u2AB0', '\u0338'},
+		"NotSucceedsTilde;":        {'\u227F', '\u0338'},
+		"NotSuperset;":             {'\u2283', '\u20D2'},
+		"ThickSpace;":              {'\u205F', '\u200A'},
+		"acE;":                     {'\u223E', '\u0333'},
+		"bne;":                     {'\u003D', '\u20E5'},
+		"bnequiv;":                 {'\u2261', '\u20E5'},
+		"caps;":                    {'\u2229', '\uFE00'},
+		"cups;":                    {'\u222A', '\uFE00'},
+		"fjlig;":                   {'\u0066', '\u006A'},
+		"gesl;":                    {'\u22DB', '\uFE00'},
+		"gvertneqq;":               {'\u2269', '\uFE00'},
+		"gvnE;":                    {'\u2269', '\uFE00'},
+		"lates;":                   {'\u2AAD', '\uFE00'},
+		"lesg;":                    {'\u22DA', '\uFE00'},
+		"lvertneqq;":               {'\u2268', '\uFE00'},
+		"lvnE;":                    {'\u2268', '\uFE00'},
+		"nGg;":                     {'\u22D9', '\u0338'},
+		"nGtv;":                    {'\u226B', '\u0338'},
+		"nLl;":                     {'\u22D8', '\u0338'},
+		"nLtv;":                    {'\u226A', '\u0338'},
+		"nang;":                    {'\u2220', '\u20D2'},
+		"napE;":                    {'\u2A70', '\u0338'},
+		"napid;":                   {'\u224B', '\u0338'},
+		"nbump;":                   {'\u224E', '\u0338'},
+		"nbumpe;":                  {'\u224F', '\u0338'},
+		"ncongdot;":                {'\u2A6D', '\u0338'},
+		"nedot;":                   {'\u2250', '\u0338'},
+		"nesim;":                   {'\u2242', '\u0338'},
+		"ngE;":                     {'\u2267', '\u0338'},
+		"ngeqq;":                   {'\u2267', '\u0338'},
+		"ngeqslant;":               {'\u2A7E', '\u0338'},
+		"nges;":                    {'\u2A7E', '\u0338'},
+		"nlE;":                     {'\u2266', '\u0338'},
+		"nleqq;":                   {'\u2266', '\u0338'},
+		"nleqslant;":               {'\u2A7D', '\u0338'},
+		"nles;":                    {'\u2A7D', '\u0338'},
+		"notinE;":                  {'\u22F9', '\u0338'},
+		"notindot;":                {'\u22F5', '\u0338'},
+		"nparsl;":                  {'\u2AFD', '\u20E5'},
+		"npart;":                   {'\u2202', '\u0338'},
+		"npre;":                    {'\u2AAF', '\u0338'},
+		"npreceq;":                 {'\u2AAF', '\u0338'},
+		"nrarrc;":                  {'\u2933', '\u0338'},
+		"nrarrw;":                  {'\u219D', '\u0338'},
+		"nsce;":                    {'\u2AB0', '\u0338'},
+		"nsubE;":                   {'\u2AC5', '\u0338'},
+		"nsubset;":                 {'\u2282', '\u20D2'},
+		"nsubseteqq;":              {'\u2AC5', '\u0338'},
+		"nsucceq;":                 {'\u2AB0', '\u0338'},
+		"nsupE;":                   {'\u2AC6', '\u0338'},
+		"nsupset;":                 {'\u2283', '\u20D2'},
+		"nsupseteqq;":              {'\u2AC6', '\u0338'},
+		"nvap;":                    {'\u224D', '\u20D2'},
+		"nvge;":                    {'\u2265', '\u20D2'},
+		"nvgt;":                    {'\u003E', '\u20D2'},
+		"nvle;":                    {'\u2264', '\u20D2'},
+		"nvlt;":                    {'\u003C', '\u20D2'},
+		"nvltrie;":                 {'\u22B4', '\u20D2'},
+		"nvrtrie;":                 {'\u22B5', '\u20D2'},
+		"nvsim;":                   {'\u223C', '\u20D2'},
+		"race;":                    {'\u223D', '\u0331'},
+		"smtes;":                   {'\u2AAC', '\uFE00'},
+		"sqcaps;":                  {'\u2293', '\uFE00'},
+		"sqcups;":                  {'\u2294', '\uFE00'},
+		"varsubsetneq;":            {'\u228A', '\uFE00'},
+		"varsubsetneqq;":           {'\u2ACB', '\uFE00'},
+		"varsupsetneq;":            {'\u228B', '\uFE00'},
+		"varsupsetneqq;":           {'\u2ACC', '\uFE00'},
+		"vnsub;":                   {'\u2282', '\u20D2'},
+		"vnsup;":                   {'\u2283', '\u20D2'},
+		"vsubnE;":                  {'\u2ACB', '\uFE00'},
+		"vsubne;":                  {'\u228A', '\uFE00'},
+		"vsupnE;":                  {'\u2ACC', '\uFE00'},
+		"vsupne;":                  {'\u228B', '\uFE00'},
+	}
 }
diff --git a/libgo/go/html/entity_test.go b/libgo/go/html/entity_test.go
index b53f866fa2d..6688ed2c43a 100644
--- a/libgo/go/html/entity_test.go
+++ b/libgo/go/html/entity_test.go
@@ -9,7 +9,15 @@ import (
 	"unicode/utf8"
 )
 
+func init() {
+	UnescapeString("") // force load of entity maps
+}
+
 func TestEntityLength(t *testing.T) {
+	if len(entity) == 0 || len(entity2) == 0 {
+		t.Fatal("maps not loaded")
+	}
+
 	// We verify that the length of UTF-8 encoding of each value is <= 1 + len(key).
 	// The +1 comes from the leading "&". This property implies that the length of
 	// unescaped text is <= the length of escaped text.
diff --git a/libgo/go/html/escape.go b/libgo/go/html/escape.go
index 8dd1f4ad2f6..dae404fab13 100644
--- a/libgo/go/html/escape.go
+++ b/libgo/go/html/escape.go
@@ -185,6 +185,7 @@ func EscapeString(s string) string {
 // UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
 // always true.
 func UnescapeString(s string) string {
+	populateMapsOnce.Do(populateMaps)
 	i := strings.IndexByte(s, '&')
 
 	if i < 0 {
diff --git a/libgo/go/html/template/attr.go b/libgo/go/html/template/attr.go
index 92d2789e804..22922e6038b 100644
--- a/libgo/go/html/template/attr.go
+++ b/libgo/go/html/template/attr.go
@@ -13,9 +13,9 @@ import (
 // other content, or affects the contents, idempotency, or credentials of a
 // network message, then the value in this map is contentTypeUnsafe.
 // This map is derived from HTML5, specifically
-// http://www.w3.org/TR/html5/Overview.html#attributes-1
+// https://www.w3.org/TR/html5/Overview.html#attributes-1
 // as well as "%URI"-typed attributes from
-// http://www.w3.org/TR/html4/index/attributes.html
+// https://www.w3.org/TR/html4/index/attributes.html
 var attrTypeMap = map[string]contentType{
 	"accept":          contentTypePlain,
 	"accept-charset":  contentTypeUnsafe,
@@ -90,7 +90,7 @@ var attrTypeMap = map[string]contentType{
 	"name":            contentTypePlain,
 	"novalidate":      contentTypeUnsafe,
 	// Skip handler names from
-	// http://www.w3.org/TR/html5/webappapis.html#event-handlers-on-elements,-document-objects,-and-window-objects
+	// https://www.w3.org/TR/html5/webappapis.html#event-handlers-on-elements,-document-objects,-and-window-objects
 	// since we have special handling in attrType.
 	"open":        contentTypePlain,
 	"optimum":     contentTypePlain,
@@ -160,7 +160,7 @@ func attrType(name string) contentType {
 
 	// Heuristics to prevent "javascript:..." injection in custom
 	// data attributes and custom attributes like g:tweetUrl.
-	// http://www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes
+	// https://www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes
 	// "Custom data attributes are intended to store custom data
 	//  private to the page or application, for which there are no
 	//  more appropriate attributes or elements."
diff --git a/libgo/go/html/template/attr_string.go b/libgo/go/html/template/attr_string.go
new file mode 100644
index 00000000000..babe70c08b8
--- /dev/null
+++ b/libgo/go/html/template/attr_string.go
@@ -0,0 +1,16 @@
+// Code generated by "stringer -type attr"; DO NOT EDIT.
+
+package template
+
+import "strconv"
+
+const _attr_name = "attrNoneattrScriptattrScriptTypeattrStyleattrURLattrSrcset"
+
+var _attr_index = [...]uint8{0, 8, 18, 32, 41, 48, 58}
+
+func (i attr) String() string {
+	if i >= attr(len(_attr_index)-1) {
+		return "attr(" + strconv.FormatInt(int64(i), 10) + ")"
+	}
+	return _attr_name[_attr_index[i]:_attr_index[i+1]]
+}
diff --git a/libgo/go/html/template/clone_test.go b/libgo/go/html/template/clone_test.go
index b500715ac6e..e292321d936 100644
--- a/libgo/go/html/template/clone_test.go
+++ b/libgo/go/html/template/clone_test.go
@@ -9,6 +9,7 @@ import (
 	"errors"
 	"fmt"
 	"io/ioutil"
+	"strings"
 	"sync"
 	"testing"
 	"text/template/parse"
@@ -262,3 +263,17 @@ func TestCloneRedefinedName(t *testing.T) {
 		}
 	}
 }
+
+// Issue 24791.
+func TestClonePipe(t *testing.T) {
+	a := Must(New("a").Parse(`{{define "a"}}{{range $v := .A}}{{$v}}{{end}}{{end}}`))
+	data := struct{ A []string }{A: []string{"hi"}}
+	b := Must(a.Clone())
+	var buf strings.Builder
+	if err := b.Execute(&buf, &data); err != nil {
+		t.Fatal(err)
+	}
+	if got, want := buf.String(), "hi"; got != want {
+		t.Errorf("got %q want %q", got, want)
+	}
+}
diff --git a/libgo/go/html/template/content.go b/libgo/go/html/template/content.go
index e7cdedc3b62..6ba87a95503 100644
--- a/libgo/go/html/template/content.go
+++ b/libgo/go/html/template/content.go
@@ -16,7 +16,7 @@ type (
 	//   2. The CSS3 rule production, such as `a[href=~"https:"].foo#bar`.
 	//   3. CSS3 declaration productions, such as `color: red; margin: 2px`.
 	//   4. The CSS3 value production, such as `rgba(0, 0, 255, 127)`.
-	// See http://www.w3.org/TR/css3-syntax/#parsing and
+	// See https://www.w3.org/TR/css3-syntax/#parsing and
 	// https://web.archive.org/web/20090211114933/http://w3.org/TR/css3-syntax#style
 	//
 	// Use of this type presents a security risk:
@@ -85,7 +85,7 @@ type (
 	URL string
 
 	// Srcset encapsulates a known safe srcset attribute
-	// (see http://w3c.github.io/html/semantics-embedded-content.html#element-attrdef-img-srcset).
+	// (see https://w3c.github.io/html/semantics-embedded-content.html#element-attrdef-img-srcset).
 	//
 	// Use of this type presents a security risk:
 	// the encapsulated content should come from a trusted source,
@@ -169,8 +169,17 @@ func stringify(args ...interface{}) (string, contentType) {
 			return string(s), contentTypeSrcset
 		}
 	}
-	for i, arg := range args {
+	i := 0
+	for _, arg := range args {
+		// We skip untyped nil arguments for backward compatibility.
+		// Without this they would be output as , escaped.
+		// See issue 25875.
+		if arg == nil {
+			continue
+		}
+
 		args[i] = indirectToStringerOrError(arg)
+		i++
 	}
-	return fmt.Sprint(args...), contentTypePlain
+	return fmt.Sprint(args[:i]...), contentTypePlain
 }
diff --git a/libgo/go/html/template/content_test.go b/libgo/go/html/template/content_test.go
index cc092f50c0c..72d56f50c14 100644
--- a/libgo/go/html/template/content_test.go
+++ b/libgo/go/html/template/content_test.go
@@ -447,10 +447,9 @@ func TestEscapingNilNonemptyInterfaces(t *testing.T) {
 	testData := struct{ E error }{} // any non-empty interface here will do; error is just ready at hand
 	tmpl.Execute(got, testData)
 
-	// Use this data instead of just hard-coding "<nil>" to avoid
-	// dependencies on the html escaper and the behavior of fmt w.r.t. nil.
+	// A non-empty interface should print like an empty interface.
 	want := new(bytes.Buffer)
-	data := struct{ E string }{E: fmt.Sprint(nil)}
+	data := struct{ E interface{} }{}
 	tmpl.Execute(want, data)
 
 	if !bytes.Equal(want.Bytes(), got.Bytes()) {
diff --git a/libgo/go/html/template/context.go b/libgo/go/html/template/context.go
index 50730d3f2b7..45be3a6a9f9 100644
--- a/libgo/go/html/template/context.go
+++ b/libgo/go/html/template/context.go
@@ -13,7 +13,7 @@ import (
 //
 // The zero value of type context is the start context for a template that
 // produces an HTML fragment as defined at
-// http://www.w3.org/TR/html5/syntax.html#the-end
+// https://www.w3.org/TR/html5/syntax.html#the-end
 // where the context element is null.
 type context struct {
 	state   state
@@ -77,6 +77,8 @@ func (c context) mangle(templateName string) string {
 // is a single token in HTML's grammar but in a template spans several nodes.
 type state uint8
 
+//go:generate stringer -type state
+
 const (
 	// stateText is parsed character data. An HTML parser is in
 	// this state when its parse position is outside an HTML tag,
@@ -96,7 +98,7 @@ const (
 	// stateHTMLCmt occurs inside an .
 	stateHTMLCmt
 	// stateRCDATA occurs inside an RCDATA element (!`),
 	}
@@ -61,7 +63,7 @@ func TestEscape(t *testing.T) {
 		{
 			"if",
 			"{{if .T}}Hello{{end}}, {{.C}}!",
-			"Hello, <Cincinatti>!",
+			"Hello, <Cincinnati>!",
 		},
 		{
 			"else",
@@ -71,17 +73,17 @@ func TestEscape(t *testing.T) {
 		{
 			"overescaping1",
 			"Hello, {{.C | html}}!",
-			"Hello, <Cincinatti>!",
+			"Hello, <Cincinnati>!",
 		},
 		{
 			"overescaping2",
 			"Hello, {{html .C}}!",
-			"Hello, <Cincinatti>!",
+			"Hello, <Cincinnati>!",
 		},
 		{
 			"overescaping3",
 			"{{with .C}}{{$msg := .}}Hello, {{$msg}}!{{end}}",
-			"Hello, <Cincinatti>!",
+			"Hello, <Cincinnati>!",
 		},
 		{
 			"assignment",
@@ -113,6 +115,16 @@ func TestEscape(t *testing.T) {
 			"{{.T}}",
 			"true",
 		},
+		{
+			"untypedNilValue",
+			"{{.U}}",
+			"",
+		},
+		{
+			"typedNilValue",
+			"{{.Z}}",
+			"<nil>",
+		},
 		{
 			"constant",
 			``,
@@ -181,7 +193,7 @@ func TestEscape(t *testing.T) {
 		{
 			"urlBranchConflictMoot",
 			``,
-			``,
+			``,
 		},
 		{
 			"jsStrValue",
@@ -199,10 +211,15 @@ func TestEscape(t *testing.T) {
 			`